napi backend: JSMethodCallback runs napi calls on the invoking thread — JS IMPs crash when ObjC calls them on foreign threads
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Anfängerfreundlichkeit
- 18/100
- Issue-Typ
- Bug
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- c, cpp, macos, nodejs, objective-c
- Bereich
- backend
Rechercherichtung
Start in NativeScript/ffi/napi/Closure.mm and compare JSMethodCallback with JSBlockCallback, which already checks closure->jsThreadId and marshals foreign-thread calls onto the JS run loop or threadsafe function. The repro needs a macOS arm64 build with -DNS_FFI_BACKEND=napi, so the first check is whether the spawned-thread ping call crashes in ObjCBridgeState::getObject. Done means that call either blocks until the JS thread returns 42 or fails with a clear error, without a SIGSEGV.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Summary
JSMethodCallback (NativeScript/ffi/napi/Closure.mm) performs napi calls — ObjCBridgeState::getObject, napi_get_named_property, napi_call_function — directly on whatever thread invoked the ffi closure, with no thread check. When a JS-backed ObjC method IMP is invoked on a non-JS thread, the bridge calls into the JS engine off-thread and crashes.
JSBlockCallback in the same file does check the calling thread (currentThreadId == closure->jsThreadId) and marshals foreign-thread invocations onto the JS side (napi_call_threadsafe_function for generic-napi builds; CFRunLoopPerformBlock(jsRunLoop, kCFRunLoopCommonModes) for embedded-runtime builds). Method IMPs get no equivalent handling. JSFunctionCallback (C-function-pointer callbacks) has the same unguarded shape.
Concrete hit in the wild: NSPrintOperation with canSpawnSeparateThread=YES invokes the operation's didRunSelector on the spawned print thread — a JS didRun IMP there crashes inside ObjCBridgeState::getObject → tryResolveBridgedClassConstructor (SIGSEGV).
Reproduction
macOS arm64, NativeScript.framework built at 5b697b39 with -DTARGET_ENGINE=none -DNS_FFI_BACKEND=napi (code identical on main), env owned by the main thread:
var Delegate = NSObject.extend(
{ ping: function () { return 42; } },
{ exposedMethods: { ping: { returns: interop.types.int32 } } }
);
var obj = Delegate.new();
obj.respondsToSelector(NSSelectorFromString("ping")); // true
NSThread.detachNewThreadSelectorToTargetWithObject(NSSelectorFromString("ping"), obj, null);
→ EXC_BAD_ACCESS (SIGSEGV) on the spawned thread:
nativescript::ObjCBridgeState::tryResolveBridgedClassConstructor(napi_env*, napi_value*, objc_class**)
nativescript::ObjCBridgeState::getObject(napi_env*, objc_object*, napi_value*, ObjectOwnership)
nativescript::JSMethodCallback(ffi_cif*, void*, void**, void*)
ffi_closure_SYSV_inner
__NSThread__start__
_pthread_start
Expected
Foreign-thread IMP/closure invocations should be marshalled to the JS thread the way JSBlockCallback already does — the caller blocks until the return value is produced, which suits synchronous IMPs — or fail deterministically with a clear error rather than corrupting engine state. As it stands, delegate methods that Apple legitimately invokes off the main thread (spawned NSPrintOperation threads, some AVFoundation/UN delegate calls on background queues) cannot be implemented in JS at all, and a missed-thread dispatch takes down the whole process.
Environment
NativeScript/runtimesmain(verified identical at5b697b39)- Generic napi backend,
TARGET_PLATFORM=macos, arm64; the sameffi/napicode path ships in the iOS napi runtime.
- Vorherrschende Sprache
- C++
- Sterne
- 27
- Forks
- 5
- Ø Merge
- 5 T. 11 Std.
- Gemergte PRs (30 T.)
- 12
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus NativeScript/runtimes
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 30/100
NativeScript/runtimes#111 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 5/5 Über eine Woche Anfängerfreundlichkeit 22/100
NativeScript/runtimes#110 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 32/100
NativeScript/runtimes#109 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 40/100
NativeScript/runtimes#107 ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 42/100
NativeScript/runtimes#106 ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in NativeScript/runtimes
Ähnliche Issues
-
go perft exits when EvalFile is unavailableEvtl. vergeben @Muawiya-contact hat das heute übernommen. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
official-stockfish/Stockfish#7292 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 77/100
arvidn/libtorrent#9149 ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Niko1221/Strata#5560 · 2 Kommentare ·
Maintainer antworten meist innerhalb von 4 Tagen
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
hyprwm/xdg-desktop-portal-hyprland#453 · 1 Kommentar ·