mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 21:56:18 -08:00
fix(embedded-mpv): stop crashing on IPC for not-yet-created sessions
The renderer was reading session.id and forwarding it to the addon, but during the loading window that id is the placeholder "embedded-mpv-starting" set by createLoadingSession. If the user adjusted volume, seeked, or toggled audio/subtitle/speed/aspect before the addon's createSession returned the real id, that placeholder id reached the addon — and the addon's getSessionOrThrow threw a raw std::runtime_error which libc++abi terminated the process on. Two fixes, defense in depth: 1. Renderer (session controller): use the canonical sessionId() signal, which is null until the addon hands back a real id, as the gate for all IPC calls. Wrap every IPC call in a guardIpc helper that swallows addon-side throws so a torn-down session or race won't surface as an uncaught promise rejection. 2. Native (embedded_mpv.mm): change getSessionOrThrow to take a Napi::Env and throw Napi::Error::New(env, ...) instead of std::runtime_error. node-addon-api converts Napi::Error to a JS exception cleanly; the previous std::runtime_error escaped the C++ frame and aborted the process when the addon was built without NAPI_CPP_EXCEPTIONS translation. Refactor splits findSession (returns nullptr) from getSessionOrThrow (env-aware) so call paths that just probe a session's existence don't pay the throw cost. The native fix needs an addon rebuild to take effect; the renderer fix prevents the crash trigger immediately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Entire-Checkpoint: f957cd9849e0
This commit is contained in:
1 parent
126025aa41
commit
9424dedafc
2 files changed
+73
-43
No files matched your search
@@ -166,18 +166,27 @@ void runOnMainSync(dispatch_block_t block)
|
||||
dispatch_sync(dispatch_get_main_queue(), block);
|
||||
}
|
||||
|
||||
std::shared_ptr<Session> getSessionOrThrow(const std::string& sessionId)
|
||||
std::shared_ptr<Session> findSession(const std::string& sessionId)
|
||||
{
|
||||
std::lock_guard<std::mutex> sessionsLock(gSessionsMutex);
|
||||
const auto iterator = gSessions.find(sessionId);
|
||||
|
||||
if (iterator == gSessions.end()) {
|
||||
throw std::runtime_error("Embedded MPV session not found.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return iterator->second;
|
||||
}
|
||||
|
||||
std::shared_ptr<Session> getSessionOrThrow(
|
||||
Napi::Env env,
|
||||
const std::string& sessionId)
|
||||
{
|
||||
auto session = findSession(sessionId);
|
||||
if (!session) {
|
||||
throw Napi::Error::New(env, "Embedded MPV session not found.");
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
void scheduleRender(const std::shared_ptr<Session>& session);
|
||||
void requestRender(const std::shared_ptr<Session>& session);
|
||||
void updateSessionError(const std::shared_ptr<Session>& session, const std::string& error);
|
||||
@@ -1604,7 +1613,7 @@ Napi::Value LoadPlayback(const Napi::CallbackInfo& info)
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto playback = info[1].As<Napi::Object>();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
const std::string streamUrl = readOptionalString(playback, "streamUrl");
|
||||
if (streamUrl.empty()) {
|
||||
throw Napi::Error::New(env, "Embedded MPV playback requires a stream URL.");
|
||||
@@ -1713,7 +1722,7 @@ Napi::Value SetBounds(const Napi::CallbackInfo& info)
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto bounds = info[1].As<Napi::Object>();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
|
||||
setSessionFrame(
|
||||
session,
|
||||
@@ -1734,7 +1743,7 @@ Napi::Value SetPaused(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
int paused = info[1].As<Napi::Boolean>().Value() ? 1 : 0;
|
||||
const int result = mpv_set_property_async(
|
||||
session->handle,
|
||||
@@ -1774,7 +1783,7 @@ Napi::Value Seek(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
const auto target = info[1].As<Napi::Number>().DoubleValue();
|
||||
const std::string targetValue = std::to_string(target);
|
||||
const char* command[] = {
|
||||
@@ -1813,7 +1822,7 @@ Napi::Value SetVolume(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
double volume = clampVolumePercent(
|
||||
info[1].As<Napi::Number>().DoubleValue()
|
||||
);
|
||||
@@ -1849,7 +1858,7 @@ Napi::Value SetAudioTrack(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
int64_t trackId = info[1].As<Napi::Number>().Int64Value();
|
||||
const int result = mpv_set_property_async(
|
||||
session->handle,
|
||||
@@ -1886,7 +1895,7 @@ Napi::Value SetSubtitleTrack(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
int64_t trackId = info[1].As<Napi::Number>().Int64Value();
|
||||
|
||||
int result = -1;
|
||||
@@ -1934,7 +1943,7 @@ Napi::Value SetSpeed(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
double speed = info[1].As<Napi::Number>().DoubleValue();
|
||||
speed = std::clamp(speed, 0.25, 4.0);
|
||||
|
||||
@@ -1973,7 +1982,7 @@ Napi::Value SetAspect(const Napi::CallbackInfo& info)
|
||||
}
|
||||
|
||||
const std::string sessionId = info[0].As<Napi::String>().Utf8Value();
|
||||
const auto session = getSessionOrThrow(sessionId);
|
||||
const auto session = getSessionOrThrow(env, sessionId);
|
||||
std::string aspect = info[1].As<Napi::String>().Utf8Value();
|
||||
if (aspect.empty()) {
|
||||
aspect = "no";
|
||||
|
||||
Reference in new issue
Block a user