diff --git a/port/unix/omrsignal.c b/port/unix/omrsignal.c index 376bdc62073..6616f6b9ff1 100644 --- a/port/unix/omrsignal.c +++ b/port/unix/omrsignal.c @@ -272,7 +272,7 @@ static void masterSynchSignalHandler(int signal, siginfo_t *sigInfo, void *conte static void masterASynchSignalHandler(int signal, siginfo_t *sigInfo, void *contextInfo); #endif /* defined(S390) && defined(LINUX) */ -static int32_t unblockSignals(void); +static int32_t unblockSignal(int signal); static void setBitMaskSignalsWithHandlers(uint32_t flags); static void unsetBitMaskSignalsWithHandlers(uint32_t flags); @@ -1269,6 +1269,18 @@ registerSignalHandlerWithOS(OMRPortLibrary *portLibrary, uint32_t portLibrarySig return OMRPORT_SIG_ERROR; } + /* If a process has blocked an asynchronous signal, then the signal stays + * blocked in the sub-processes across fork(s) and exec(s). A blocked + * signal prevents its OS signal handler to be invoked. A signal is + * unblocked as an OS signal handler is installed for it in case a + * parent process has blocked it. + */ + if (OMR_ARE_ALL_BITS_SET(OMRPORT_SIG_FLAG_SIGALLASYNC, portLibrarySignalNo)) { + if (0 != unblockSignal(unixSignalNo)) { + return OMRPORT_SIG_ERROR; + } + } + memset(&newAction, 0, sizeof(struct sigaction)); /* Do not block any signals. */ @@ -1606,16 +1618,6 @@ initializeSignalTools(OMRPortLibrary *portLibrary) } #endif /* !defined(J9ZOS390) */ - /* If a process has blocked signals, then the signals stay blocked in the - * sub-processes across fork(s) and exec(s). Blocked signals prevent signal - * handlers to be invoked. Signals listed in signalMap should be unblocked - * during initialization in case a parent process has blocked any of those - * signals. - */ - if (0 != unblockSignals()) { - return -1; - } - #if defined(OMR_PORT_ASYNC_HANDLER) if (J9THREAD_SUCCESS != createThreadWithCategory( &asynchSignalReporterThread, @@ -1870,19 +1872,18 @@ omrsig_chain_at_shutdown_and_exit(struct OMRPortLibrary *portLibrary) #endif /* defined(OMRPORT_OMRSIG_SUPPORT) */ /** - * This function will unblock signals listed in signalMap by changing the - * signal mask of the calling thread. This function should only be called - * during initialization from the main thread and before creation of other - * threads. + * This function will unblock a signal by changing the signal mask of the + * calling thread. This function is only invoked while registering a signal + * handler with the OS (registerSignalHandlerWithOS), which is protected by + * registerHandlerMonitor for synchronization. * - * @param[in] void + * @param[in] signal the signal to be unblocked * * @return 0 on success and non-zero on failure */ static int32_t -unblockSignals(void) { +unblockSignal(int signal) { int32_t rc = 0; - int i = 0; sigset_t signalSet; rc = sigemptyset(&signalSet); @@ -1891,18 +1892,13 @@ unblockSignals(void) { goto exit; } - /* Iterate through all signals listed in signalMap. */ - for (i = 0; i < sizeof(signalMap) / sizeof(signalMap[0]); i++) { - /* Add the current signal to the signal set. */ - int currentSignal = signalMap[i].unixSignalNo; - rc = sigaddset(&signalSet, currentSignal); - if (0 != rc) { - Trc_PRT_signal_unblockSignals_sigaddset_failed(currentSignal, rc, errno); - goto exit; - } + rc = sigaddset(&signalSet, signal); + if (0 != rc) { + Trc_PRT_signal_unblockSignals_sigaddset_failed(signal, rc, errno); + goto exit; } - /* Unblock the signals listed in signalMap. */ + /* Unblock the signal. */ rc = pthread_sigmask(SIG_UNBLOCK, &signalSet, NULL); if (0 != rc) { Trc_PRT_signal_unblockSignals_pthread_sigmask_failed(rc, errno);