Skip to content

fix(macos): tray init deadlock on the Nucleus Tao backend#423

Merged
kdroidFilter merged 3 commits into
masterfrom
fix/tray-init-main-thread-deadlock
Jul 18, 2026
Merged

fix(macos): tray init deadlock on the Nucleus Tao backend#423
kdroidFilter merged 3 commits into
masterfrom
fix/tray-init-main-thread-deadlock

Conversation

@kdroidFilter

Copy link
Copy Markdown
Collaborator

Summary

  • startTray() spawned MacTray-Thread and blocked the caller on a CountDownLatch until nativeInitTray completed. tray_init hops to the GCD main queue when called off the macOS main thread — but on the Nucleus Tao backend the caller IS the main thread, parked on the latch inside the event-loop callback, so the main queue never drained and the app deadlocked a few seconds after startup (reported via spindump on CozySpace 1.2.2).
  • Create/init now runs inline on the calling thread: tray_init executes directly when already on the main thread, and main.syncs otherwise (the main thread is free in that case). The 100 ms tray_loop polling loop is gone — status-item events are delivered by the application's own AppKit run loop.
  • Removes the dead JNA-era mouse-hook JNI code (nativeInstallMouseHook & co, no Kotlin callers): its implementation invoked the Java callback inside the WH_MOUSE_LL proc, which stalls the system-wide mouse during any JVM safepoint — removed so the pattern cannot be reused.
  • Publications are now signed only when signingInMemoryKey is present, so publishToMavenLocal works locally; CI signing is unchanged (ORG_GRADLE_PROJECT_signingInMemoryKey).

Test plan

  • macOS + Tao backend (CozySpace): app no longer freezes at startup in tray mode
  • Tray icon appears, left-click toggles the popup, right-click menu works
  • Windows/Linux: tray behavior unchanged (managers untouched)
  • publishToMavenLocal succeeds without signing keys

…hing on a dedicated thread

startTray() spawned MacTray-Thread and blocked the caller on a CountDownLatch
until nativeInitTray completed. tray_init hops to the GCD main queue when
called off the macOS main thread — but on the Nucleus Tao backend the caller
IS the main thread, parked on the latch inside the event-loop callback, so
the main queue never drained and the app deadlocked at startup.

Run create/init inline on the calling thread: tray_init executes directly
when already on the main thread and main.syncs otherwise (the main thread is
free in that case). Drop the tray_loop polling loop too — status-item events
are delivered by the application's own AppKit run loop, and pumping nextEvent
from a background thread's main.sync could steal events from the real loop.
nativeInstallMouseHook/nativeRunMouseHookLoop/nativeStopMouseHook/
nativeGetLastMouseHookClick had no Kotlin callers (JNA-era leftover). The
implementation also invoked the Java callback inside the WH_MOUSE_LL proc,
which stalls the system-wide mouse during any JVM safepoint — removed so the
pattern cannot be reused.
publishToMavenLocal failed locally with 'no configured signatory'. CI keeps
signing through ORG_GRADLE_PROJECT_signingInMemoryKey.
@kdroidFilter
kdroidFilter merged commit f70af80 into master Jul 18, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant