JDK-4953058 : The JVM unblocks SIGUSR1 if the -XX:+UseAltSigs option is used.
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.2
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: solaris_8
  • CPU: sparc
  • Submitted: 2003-11-12
  • Updated: 2012-10-08
  • Resolved: 2006-11-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2_14 b01Fixed
Description
Name: jl125535			Date: 11/12/2003


FULL PRODUCT VERSION :
java version "1.4.2_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_01-b06)
Java HotSpot(TM) Client VM (build 1.4.2_01-b06, mixed mode)


FULL OS VERSION :
SunOS gizmo 5.8 Generic_108528-14 sun4u sparc SUNW,Ultra-4

A DESCRIPTION OF THE PROBLEM :
I have a problem using the JNI interface to call some library methods
written in java from some C code. The C code uses SIGUSR1 for
asynchronous events. However JNI_CreateJavaVM unblocks SIGUSR1
even if I supply the "-XX:+UseAltSigs" option.

The C code relies on the fact that SIGUSR1 is normally blocked and
only handled after a sigwait() call. However after the Java VM is
initialised SIGUSR1 is unblocked.

This prevents our entire application working at all!  The problem
was introduced in Java 1.4.1 and still persists in version 1.4.2

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Build and run the supplied test program that uses the JNI.

Follow the instructions.



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
We should get the output:

Before call to JNI_CreateJavaVM
SIGUSR1 is blocked
After call to JNI_CreateJavaVM
SIGUSR1 is blocked!
  From another terminal send the signal SIGUSR1 to this process
Using the command: 'kill -USR1 ...'

++ SIGUSR1 ++

ACTUAL -
Before call to JNI_CreateJavaVM
SIGUSR1 is blocked
After call to JNI_CreateJavaVM
SIGUSR1 is _NOT_ blocked!
  From another terminal send the signal SIGUSR1 to this process
Using the command: 'kill -USR1 26760'
26760:  java_signals_bug
-----------------  lwp# 1 / thread# 1  --------------------
 feb9c0c8 lwp_sema_wait (29120)
 ff109af4 _park    (29120, ff12e000, 0, 29060, 0, 0) + 114
 ff1097bc _swtch   (29060, ffffffff, ff12e000, 5, 1000, 290f4) + 424
 ff11a018 cond_timedwait_sig (0, 0, ffbef4a8, ffbef4ac, 0, ff12efa0) + 180
 ff11a2d8 __sigtimedwait (29060, 0, 0, ff12e000, 30, 0) + 1f0
 feb93880 __posix_sigwait (0, 0, ffbef588, ffbef590, ffbef096, 0) + 20
 00011a24 _wait_for_signal (0, febc1a84, febbdc80, febbdc80, 10, 0) + a4
 00011f40 main     (1, ffbef6ec, ffbef6f4, 22c00, 0, 0) + 2c0
 00011858 _start   (0, 0, 0, 0, 0, 0) + 108
-----------------  lwp# 2 / thread# 2  --------------------
 feb9ba18 signotifywait ()
 ff10ed90 _dynamiclwps (ff12e000, 59, 0, 0, ffbef06c, 4) + 1c
 ff11206c thr_yield (0, 0, 0, 0, 0, 0) + 8c
-----------------  lwp# 3  --------------------------------
 feb9c07c lwp_cond_wait (ff135550, ff135560, ff12edb8)
 ff1090dc _age     (0, ff12eda4, ff12e000, 0, 0, 4) + 74
 feb99618 _door_return (febf5cb0, ff10a770, 0, 0, 0, 0) + 68
-----------------  lwp# 4 / thread# 4  --------------------
 feb9c65c waitid   (0, 68cc, fdf80db0, 103)
 feb56690 _waitpid (0, fdf80e9c, 100, fdf80e9c, 3, fdf80f05) + 60
 feb91b78 system   (fdf81084, 126a8, 6888, 0, 0, 0) + 25c
 000118dc _sigusr1_handler (10, fdf81988, fdf816d0, 0, 0, 0) + 5c
 ff11b82c __sighndlr (10, fdf81988, fdf816d0, 11880, fdf81e14, fdf81e04) + c
 ff118504 sigacthandler (10, fdf81d70, 0, 0, 0, ff12e000) + 708
 --- called from signal handler with signal 16 (SIGUSR1) ---
 feb9c080 ___lwp_cond_wait (2d4b0, 2d498, fdf81ad0, 0, 0, fdf81ac8) + 8
 feb936d4 _lwp_cond_timedwait (1f045e60, 3f852731, fdf81ba4, 2d498, 2d4b0, 1) +
98
 fecd2fc8 __1cHMonitorEwait6Mil_i_ (0, 1, 0, 0, ff03cd60, ff12e000) + 2b0
 fecd37e0 __1cIVMThreadEloop6M_v_ (ff045fb0, ff03cdc4, ff03cdc0, 0, 0, 0) + 130
 fecd34b0 __1cIVMThreadDrun6M_v_ (b34f0, 0, 0, 0, 0, 0) + 78
 fecd33c0 _start   (b34f0, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (b34f0, 0, 0, 0, 0, 0) + 40
-----------------  lwp# 5  --------------------------------
 feb995bc door     (0, 0, 0, 0, febe5d10, 4)
 ff116be0 _sc_door_func (4, ff12f690, ff12f6a8, 3, ff12e000, 1) + 54
 ff10a770 _lwp_start (febe5d70, 0, 6000, febf5b74, 0, 0) + 18
 ff11206c thr_yield (0, 0, 0, 0, 0, 0) + 8c
-----------------  lwp# 6 / thread# 5  --------------------
 feb9c07c lwp_cond_wait (b53a8, b5390, 0)
 feb935c0 _lwp_cond_wait (b53a8, b5390, 0, b6268, 0, 0) + c
 fece7aa4 __1cNObjectMonitorEwait6MxipnGThread__v_ (b5358, 0, 5400, 57f4, b4988,
 5274) + 61c
 fece7094 __1cSObjectSynchronizerEwait6FnGHandle_xpnGThread__v_ (fa3816fc, 0, 0,
 b4988, b4988, 37df48) + 180
 fece6d94 JVM_MonitorWait (b4a14, fa3817f4, 0, 0, fa4150c4, 0) + 130
 fa40bbc8 ???????? (f2000380, b6, fa381874, ffffffff, fa4150c4, fa381790)
 fa405c64 ???????? (f2000380, b6, fa381878, fa415064, b4988, fa381810)
 fa405c64 ???????? (fa381908, 0, 0, fa4153a0, 3611ec, fa3818a8)
 fa400118 ???????? (fa381994, fa381c08, a, f6055c20, fa40aae0, fa381b28)
 fecd4bec __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallAr
guments_pnGThread__v_ (fa381c00, fa381a60, fa381b20, b4988, b4988, fa381a74) + 2
5c
 fece6938 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle
_4pnRJavaCallArguments_pnGThread__v_ (ff028000, b4f28, fa381b14, fa381b10, fa381
b20, b4988) + 190
 fece6798 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsym
bolHandle_5pnGThread__v_ (fa381c00, fa381bfc, fa381bf0, fa381be8, fa381be0, b498
8) + 60
 fece6720 __1cMthread_entry6FpnKJavaThread_pnGThread__v_ (b4988, b4988, 7bd38, b
4f28, 341ae0, fece6408) + 1d8
 fece6430 __1cKJavaThreadDrun6M_v_ (b4988, 0, 0, 0, 0, 0) + 254
 fecd33c0 _start   (b4988, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (b4988, 0, 0, 0, 0, 0) + 40
-----------------  lwp# 7 / thread# 6  --------------------
 feb9c07c lwp_cond_wait (b6cf8, b6ce0, 0)
 feb935c0 _lwp_cond_wait (b6cf8, b6ce0, 0, 1, 0, 0) + c
 fece7aa4 __1cNObjectMonitorEwait6MxipnGThread__v_ (b6ca8, 0, 5400, 57f4, b62a8,
 5274) + 61c
 fece7094 __1cSObjectSynchronizerEwait6FnGHandle_xpnGThread__v_ (fa281674, 0, 0,
 b62a8, b62a8, 37df48) + 180
 fece6d94 JVM_MonitorWait (b6334, fa281774, 0, 0, fa4150c4, 0) + 130
 fa40bbc8 ???????? (f2000490, b6, fa281778, fa4141e8, fa4150c4, fa281708)
 fa405c64 ???????? (f2000478, b6, fa281884, fa415064, fa4150c4, fa2817a8)
 fa405b10 ???????? (f2000478, b6, fa281904, fa415064, b62a8, fa281828)
 fa405b10 ???????? (fa281908, 0, 0, fa281954, 3611ec, fa2818a8)
 fa400118 ???????? (fa281994, fa281c08, a, f60572a0, fa40aae0, fa281b28)
 fecd4bec __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallAr
guments_pnGThread__v_ (fa281c00, fa281a60, fa281b20, b62a8, b62a8, fa281a74) + 2
5c
 fece6938 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandle
_4pnRJavaCallArguments_pnGThread__v_ (ff028000, b6848, fa281b14, fa281b10, fa281
b20, b62a8) + 190
 fece6798 __1cJJavaCallsMcall_virtual6FpnJJavaValue_nGHandle_nLKlassHandle_nMsym
bolHandle_5pnGThread__v_ (fa281c00, fa281bfc, fa281bf0, fa281be8, fa281be0, b62a
8) + 60
 fece6720 __1cMthread_entry6FpnKJavaThread_pnGThread__v_ (b62a8, b62a8, 7bd78, b
6848, 341ae0, fece6408) + 1d8
 fece6430 __1cKJavaThreadDrun6M_v_ (b62a8, 0, 0, 0, 0, 0) + 254
 fecd33c0 _start   (b62a8, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (b62a8, 0, 0, 0, 0, 0) + 40
-----------------  lwp# 8 / thread# 7  --------------------
 feb9a254 poll     (fa181b48, 0, a)
 feb4cf8c select   (0, 0, 0, fa181b48, febbd1a4, fa181b48) + 348
 ff11b13c select   (0, ff03d5ec, b, ff028000, 0, 0) + 34
 fed038ac __1cCosFsleep6FpnGThread_xi_i_ (b90e8, 0, a, 0, 0, 0) + 188
 fed0368c __1cNWatcherThreadDrun6M_v_ (b90e8, 0, 0, 0, 0, 0) + 68
 fecd33c0 _start   (b90e8, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (b90e8, 0, 0, 0, 0, 0) + 40
-----------------  lwp# 9 / thread# 8  --------------------
 feb9c07c lwp_cond_wait (2ce50, 2ce38, 0)
 feb935c0 _lwp_cond_wait (2ce50, 2ce38, 3552b8, ff12e000, f1f81e14, 0) + c
 fecd2e24 __1cHMonitorEwait6Mil_i_ (0, 0, 0, 0, ff03cd60, 0) + 10c
 fed043b8 __1cUSuspendCheckerThreadDrun6M_v_ (b9a38, 0, 0, 0, 0, 0) + 88
 fecd33c0 _start   (b9a38, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (b9a38, 0, 0, 0, 0, 0) + 40
-----------------  lwp# 10 / thread# 9  --------------------
 feb9c0c8 lwp_sema_wait (f1e81e30)
 ff109af4 _park    (f1e81e30, ff12e000, 0, f1e81d70, 0, 0) + 114
 ff1094f0 _swtch   (f1e81d70, ffffffff, ff12e000, 5, 1000, 0) + 158
 ff10cca0 sema_wait (ff046a08, ff1398ec, 5000, 10000, 534d, 1) + bc
 fed052a0 __1cVcheck_pending_signals6Fi_i_ (ff03e9b8, ff03d5cc, ff03fdc8, ff046a
08, 0, 2f) + 168
 fed04f14 __1cTsignal_thread_entry6FpnKJavaThread_pnGThread__v_ (ff03fdc8, ff046
264, ff046298, ba928, 341ae0, fece6408) + 94
 fece6430 __1cKJavaThreadDrun6M_v_ (ba388, 0, 0, 0, 0, 0) + 254
 fecd33c0 _start   (ba388, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (ba388, 0, 0, 0, 0, 0) + 40
-----------------  lwp# 11 / thread# 10  --------------------
 feb9c07c lwp_cond_wait (2d950, 2d938, 0)
 feb935c0 _lwp_cond_wait (2d950, 2d938, 3552b8, ff03cd60, 2d938, 0) + c
 fecd307c __1cHMonitorEwait6Mil_i_ (0, 0, 0, 321e94, ff03cd60, 0) + 364
 fed05ccc __1cNCompileBrokerUcompiler_thread_loop6F_v_ (badf8, badf8, 7c098, bb3
98, 341ae0, fece6408) + 1c0
 fece6430 __1cKJavaThreadDrun6M_v_ (badf8, 0, 0, 0, 0, 0) + 254
 fecd33c0 _start   (badf8, ff12f690, 1, 1, ff12e000, 0) + 20
 ff11b730 _thread_start (badf8, 0, 0, 0, 0, 0) + 40
--------------------------  thread# 3  --------------------
 ff10ddf8 _reap_wait (ff1329e8, 204e4, 0, ff12e000, 0, 0) + 38
 ff10db50 _reaper  (ff12ee38, ff134748, ff1329e8, ff12ee10, 1, fe400000) + 38
 ff11b730 _thread_start (0, 0, 0, 0, 0, 0) + 40


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*-----------------------------------------------------------------------------
** java_signals_bug.c:
**
** This program illustrates a problem using the JVM from native code. Our
** application uses SIGUSR1 for its own purposes. From Java 1.4.1 the JVM
** uses these signals unless the '-XX:+UseAltSigs' option is used. However
** the JVM still unblocks this signal even though it does not install a
** signal handler for this signal.
**
** This test program illustrates the problem.
**
** Compiled with:
**   /opt/SUNWspro/bin/cc -o java_signals_bug.o -DPTHREADS -D_REENTRANT -I...
**      -KPIC -g -mt  -c java_signals_bug.c
** Linked with:
**   /opt/SUNWspro/bin/cc -o java_signals_bug java_signals_bug.o -L...
**      -ljvm -L... -ljava  -lintl -lnsl -lsocket -lpthread -lgen -lm -lelf
**      -ldl -lrt -g
**
** Tested on Solaris:
**   SunOS 5.8 Generic_108528-14 sun4u sparc SUNW,Ultra-4
** JVM: V1.4.1_02 and 1.4.2
**
**---------------------------------------------------------------------------*/

#include <pthread.h>

/* For sigwait */
#define _POSIX_PTHREAD_SEMANTICS 1

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

#include <jni.h>        /* Java Native Interface */

/* Dummy signal handler for SIGUSR1 */
void _sigusr1_handler(int sid)
{
    /* This function should _not_ be called! */
    char path[1204];
    /* Do something safe here! */
    sprintf(path, "/usr/proc/bin/pstack %d", getpid());
    system(path);
}

/* Function to process SIGUSR1 */
void _signalled_event_handler(int sid)
{
    /* Test program just prints the signal */
    printf("++ SIGUSR1 ++\n");
    fflush(stdout);
}

void _wait_for_signal(void)
{
    sigset_t    zeromask;
    int         err_,sig_;

    sigemptyset(&zeromask);
    sigaddset(&zeromask, SIGUSR1);
    sigaddset(&zeromask, SIGHUP);
    sigaddset(&zeromask, SIGTERM);
    /* Enable ctrl-c and ctrl-\ handling */
    sigaddset(&zeromask, SIGINT);
    sigaddset(&zeromask, SIGQUIT);
    err_ = sigwait(&zeromask, &sig_);
    if (err_)
        fprintf(stderr, "ERROR sigwait() = %d\n", err_);
    if (sig_ == SIGUSR1)
        _signalled_event_handler(sig_);
    else if (sig_ == SIGHUP || sig_ == SIGTERM ||
             sig_ == SIGINT || sig_ == SIGQUIT)
    {
        fprintf(stderr,
                "** Received signal to terminate application (%d)\n", sig_);
        exit(0);
    }
    else
        fprintf(stderr, "WARNING: caught unexpected signal (%d)\n", sig_);
}

void check_sigusr1_state(void)
{
    sigset_t            sigset;

    /* Check state of SIGUSR1 */
    if (sigprocmask(SIG_SETMASK, NULL, &sigset) < 0)
    {
        fprintf(stderr, "Cannot read signal mask (%d)\n", errno);
        exit(1);
    }
    if (sigismember(&sigset, SIGUSR1) == 0)
    {
        printf("SIGUSR1 is _NOT_ blocked!\n");
    } else {
        printf("SIGUSR1 is blocked\n");
    }
    fflush(stdout);
}

int main(void)
{
    struct sigaction    act;
    sigset_t            sigset;
    JavaVMInitArgs      vm_args;
    JavaVMOption        options[6];
    int                 i;
    jint                res;
    JNIEnv              *env;
    JavaVM              *jvm;

    sigemptyset(&sigset);
    sigaddset(&sigset, SIGUSR1);

    /* Install dummy SIGUSR1 handler */
    act.sa_handler = _sigusr1_handler;
    act.sa_mask    = sigset;
    act.sa_flags   = SA_RESTART;

    i = sigaction(SIGUSR1, &act, NULL);
    if (i == -1)
    {
        fprintf(stderr, "Failed to install dummy SIGUSR1 handler!\n");
        exit(1);
    }

    /* Ensure that SIGUSR1 is blocked. */
    sigemptyset(&sigset);
    sigaddset(&sigset, SIGUSR1);
    if (sigprocmask(SIG_BLOCK, &sigset, NULL) < 0)
    {
        fprintf(stderr, "Failed to block SIGUSR1!\n");
        exit(1);
    }

    i=0;
    /* IMPORTANT: Stop the JVM using SIGUSR1 */
    options[i++].optionString = "-XX:+UseAltSigs";
/*    options[i++].optionString = "-verbose"; */
    options[i++].optionString = "-Xcheck:jni";

    vm_args.version     = JNI_VERSION_1_4;
    vm_args.options     = options;
    vm_args.nOptions    = i;
    vm_args.ignoreUnrecognized = 1;

    /* Check SIGUSR1 state */
    printf("Before call to JNI_CreateJavaVM\n");
    check_sigusr1_state();

    res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

    /* Check SIGUSR1 state */
    printf("After call to JNI_CreateJavaVM\n");
    check_sigusr1_state();

    if (res < 0)
    {
        fprintf(stderr, "JNI: Cannot create Java VM (error=%d)\n", res);
        exit(1);
    }

    printf("From another terminal send the signal SIGUSR1 to this process\n");
    printf("Using the command: 'kill -USR1 %d'\n", getpid());
    fflush(stdout);

    /* Loop round waiting for signals */
    while (1)
    {
        _wait_for_signal();
    }

    return (0);
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None found.
(Incident Review ID: 214950) 
======================================================================

Comments
EVALUATION This has been fixed in 1.5.0.
11-06-2004

SUGGESTED FIX A fix for this should be incorporated into 1.4.1 and 1.4.2. My apologies for creating this bug in 1.4.1. This was fixed in 1.5.0 as part of 4840909 - Solaris 10 changes to support SIGJVM1, SIGJVM2. Credit for the fix goes to Dave Dice who caught this during his code review. The problem is that the unblocked signal set (unblocked_sigs) is initialized in signal_sets_init() using the default value of os::Solaris::SIGinterrupt() before install_signal_handlers() is called where the check is made for UseAltSigs. This bug also applies to os::Solaris::SIGasync() and should be fixed for that as well. If you want the entire fix, i.e. the Solaris 10 fix to no longer use SIGUSR1 even without the UseAltSigs flag, then you can take the entire set of changes from 4840909 putback in April 2003 to the 1.5.0 tree. This includes: jvm_solaris.h 1.15 fix comment os_solaris.cpp 1.263.5.1 key changes os_solaris.hpp 1.77.3.1 Add signal_sets_init to Solaris class so it can call set_SIGinterrupt etc. If you want to minimize the changes you make, you can skip jvm_solaris.h comment changes. You need the os_solaris.hpp changes. And you can extract the non-Solaris 10 improvements from os_solaris.cpp: 1. in signal_sets_init: change sigaddset(&unblocked_sigs, os::Solaris::SIGinterrupt()); sigaddset(&unblocked_sigs, os::Solaris::SIGasync()); to if (UseAltSigs) { os::Solaris::set_SIGinterrupt(ALT_INTERRUPT_SIGNAL); os::Solaris::set_SIGasync(ALT_ASYNC_SIGNAL); } else { os::Solaris::set_SIGinterrupt(INTERRUPT_SIGNAL); os::Solaris::set_SIGasync(ASYNC_SIGNAL); } 2. in install_signal_handlers change: if (UseAltSigs) { os::Solaris::set_SIGinterrupt(ALT_INTERRUPT_SIGNAL); os::Solaris::set_SIGasync(ALT_ASYNC_SIGNAL); // Pre-1.4.1 Libjsig limited to signal chaining signals <= 32 so // can not register overridable signals which might be > 32 if (libjsig_is_loaded && libjsigversion <= JSIG_VERSION_1_4_1) { // Tell libjsig jvm has finished setting signal handlers (*end_signal_setting)(); libjsigdone = true; } } to if (os::Solaris::SIGinterrupt() > OLDMAXSIGNUM || os::Solaris::SIGasync() > OL DMAXSIGNUM) { // Pre-1.4.1 Libjsig limited to signal chaining signals <= 32 so // can not register overridable signals which might be > 32 if (libjsig_is_loaded && libjsigversion <= JSIG_VERSION_1_4_1) { // Tell libjsig jvm has finished setting signal handlers (*end_signal_setting)(); libjsigdone = true; } } My recommendation, since 1.4.2 is the default version shipping for Solaris 10, is to take the entire set of changes. ###@###.### 2003-11-17
17-11-2003