openjdk/jdk · warning
VM warning: the use of signal() and sigset() for signal cha
Error message
VM warning: the use of signal() and sigset() for signal chaining was deprecated in version 16.0 and will be removed in a future release. Use sigaction() instead.
What it means
Deprecation notice from libjsig (the JDK's signal-chaining library, preloaded via LD_PRELOAD on Solaris/Linux HotSpot). If application or library code calls signal() or sigset() (instead of sigaction()) to install a signal handler while the JVM is running, libjsig intercepts the call, prints this one-time warning, and forwards the registration to the JVM's chained handling. Behavior is still correct; the API is deprecated because signal()'s unreliable semantics do not compose well with JVM signal chaining.
Source
Thrown at src/java.base/unix/native/libjsig/jsig.c:97
* other than the jvm thread should wait. */
if (jvm_signal_installing) {
/* tid is not initialized until jvm_signal_installing is set to true. */
if (pthread_equal(tid, pthread_self()) == 0) {
do {
pthread_cond_wait(&cond, &mutex);
} while (jvm_signal_installing);
}
}
}
static void signal_unlock() {
pthread_mutex_unlock(&mutex);
}
static void print_deprecation_warning() {
if (!warning_printed) {
warning_printed = true;
fprintf(stderr, HOTSPOT_VM_DISTRO " VM warning: the use of signal() and sigset() "
"for signal chaining was deprecated in version 16.0 and will "
"be removed in a future release. Use sigaction() instead.\n");
}
}
static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
bool is_sigset) {
sa_handler_t res;
if (os_signal == NULL) {
if (!is_sigset) {
os_signal = (signal_function_t)dlsym(RTLD_NEXT, "signal");
} else {
os_signal = (signal_function_t)dlsym(RTLD_NEXT, "sigset");
}
if (os_signal == NULL) {
printf("%s\n", dlerror());
exit(0);View on GitHub (pinned to 88dfb74bbe)
Solutions
- Change the offending native code to install handlers with sigaction() instead of signal()/sigset() — this is the only real fix
- Identify the caller: run under a debugger with a breakpoint on signal(), or use tools like 'ltrace -e signal' to catch who calls it
- If the caller is a third-party library, upgrade to a version using sigaction or report it upstream
- The warning is printed only once per process; it is harmless unless the API is actually removed in a future release — plan the migration before then
Example fix
// before (C) signal(SIGTERM, my_handler); // after struct sigaction sa; sa.sa_handler = my_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTERM, &sa, NULL);
Defensive patterns
Strategy: validation
Validate before calling
// Audit native code linked into the process for deprecated calls before shipping: // ltrace -e signal -e sigset -- ./myapp 2>&1 | grep -v '^---' // or link-time: nm -D libmynative.so | grep -w signal
Prevention
- Standardize on sigaction() in all JNI/native libraries that touch signals
- Watch JDK release notes: the removal of signal()/sigset() chaining support is planned, so migrate before upgrading
- If you must keep JVM signal chaining, preload libjsig and register handlers via sigaction only
When it happens
Trigger: Any call to signal() or sigset() from JVM-attached native code (JNI library, agent, or the application itself) after libjsig was initialized. Typical sources: C libraries installing SIGINT/SIGTERM/SIGPIPE handlers, legacy code ported from older Unix codebases.
Common situations: Running a Java app that loads a third-party native library which registers signal handlers with signal(); using tools or daemons that call signal() during startup before/after JVM init; upgrading to JDK 16+ where the warning was introduced and seeing it in logs.
Related errors
- no '/' found in the full path of the executable
- Error: Out of memory in ADLC\n
- JVM caught ASAN Error
- failed to get the full path of the executable: %lu
- no '\' found in the full path of the executable
AI-assisted analysis of openjdk/jdk@88dfb74bbe (2026-08-14).
Data as JSON: /api/errors/87e3924b370e8621.
Report an issue: GitHub.