mirror of
https://github.com/wgtunnel/Nucleus.git
synced 2026-10-09 14:40:54 -07:00
An unhandled exception on the Tao main thread used to be cleared at the JNI boundary, leaving a frozen, silent, unclosable window. Default path now: SEVERE log with the full stack trace, blocking native error dialog, clean loop exit, rethrow from TaoApplication.run (taoApplication turns it into exitProcess(1); 0 stays the normal-quit code). - nativeShowErrorDialog in the existing nucleus_tao crate. macOS only for now via CFUserNotificationDisplayAlert - out-of-process, any-thread, no NSApp/run-loop dependency, so it is safe after the loop teardown where tao's latched [NSApp stop:] makes an NSAlert runModal session return immediately, and it cannot re-enter tao's non-reentrant handler mutex the way a modal pumped inside a callback frame can (Dock-reopen / deep link). Windows and Linux are silent no-ops until their implementations land. - TaoApplication.reportFatal: first report wins (AtomicReference), exit() posted before logging so even a throwing formatter cannot freeze the loop; dialog + rethrow happen in run() after the loop exits. State is reset on run() entry so the loop can be re-run. - taoApplication installs a CoroutineExceptionHandler routing composition and effect failures (recomposition, LaunchedEffect, setContent) to the fatal path - previously they hit stderr and the process exited 0. The macOS FrameDispatcher render loop gets the same handler (a frame exception silently stopped repainting under the SupervisorJob). - Non-fatal native->JVM upcalls (deep link, a11y actions) and TaoMainDispatcher's swallowed block failures now log at SEVERE instead of vanishing / printStackTrace. - -Dnucleus.tao.fatalErrorDialog=false skips the dialog for unattended runs (CI, AOT training). - swing-tao-demo catches the documented rethrow and exits 1 instead of leaving a zombie process on the non-daemon EDT. Verified end-to-end on macOS: raw-run fatal (dialog + rethrow, exit 42 from the caller) and Compose-composition fatal (CEH -> dialog -> exit 1).