Skip to content

Fix process-wide signal handler override in JNI_OnLoad#632

Open
rfcom wants to merge 1 commit intoFazecast:masterfrom
rfcom:fix/signal-handlers-jvm-compatibility
Open

Fix process-wide signal handler override in JNI_OnLoad#632
rfcom wants to merge 1 commit intoFazecast:masterfrom
rfcom:fix/signal-handlers-jvm-compatibility

Conversation

@rfcom
Copy link
Copy Markdown

@rfcom rfcom commented May 4, 2026

JNI_OnLoad called sigaction() to set SIGUSR1 and SIGUSR2 to SIG_IGN, overwriting the JVM's signal chain process-wide without saving the previous handler (third argument NULL instead of &oldAction).

On Linux, JavaScriptCore (WebKit) uses SIGUSR1 to suspend threads during garbage collection: the GC thread sends SIGUSR1 via pthread_kill to all threads, and each thread's handler calls sem_post to acknowledge. With SIG_IGN, the acknowledgement never arrives and the GC thread waits indefinitely, causing a permanent hang in any JavaFX WebView application that uses jSerialComm.

Remove all sigaction() calls from JNI_OnLoad. Replace with per-thread pthread_sigmask() calls in the two event reader threads, which blocks only the signals that could interrupt serial port I/O in those specific threads without affecting the rest of the process.

SIGUSR1 and SIGUSR2 are intentionally NOT blocked. These threads must remain suspendable by the JVM GC — blocking them would prevent garbage collection from working on those threads.

The other signals (SIGHUP, SIGTTOU, SIGTTIN) are also unnecessary process-wide because serial ports are opened with O_NOCTTY, which prevents them from becoming the controlling terminal.

Fixes #631

JNI_OnLoad called sigaction() to set SIGUSR1 and SIGUSR2 to SIG_IGN,
overwriting the JVM's signal chain process-wide without saving the
previous handler (third argument NULL instead of &oldAction).

On Linux, JavaScriptCore (WebKit) uses SIGUSR1 to suspend threads during
garbage collection: the GC thread sends SIGUSR1 via pthread_kill to all
threads, and each thread's handler calls sem_post to acknowledge. With
SIG_IGN, the acknowledgement never arrives and the GC thread waits
indefinitely, causing a permanent hang in any JavaFX WebView application
that uses jSerialComm.

Remove all sigaction() calls from JNI_OnLoad. Replace with per-thread
pthread_sigmask() calls in the two event reader threads, which blocks
only the signals that could interrupt serial port I/O in those specific
threads without affecting the rest of the process.

SIGUSR1 and SIGUSR2 are intentionally NOT blocked. These threads must
remain suspendable by the JVM GC — blocking them would prevent garbage
collection from working on those threads.

The other signals (SIGHUP, SIGTTOU, SIGTTIN) are also unnecessary
process-wide because serial ports are opened with O_NOCTTY, which
prevents them from becoming the controlling terminal.

Fixes Fazecast#631
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.

JNI_OnLoad overrides JVM SIGUSR1/SIGUSR2 signal handlers process-wide, causing indefinite GC hang with JavaFX WebKit

1 participant