Skip to content

Commit

Permalink
Add implementation of omrsig_set_single_async_signal_handler [Unix]
Browse files Browse the repository at this point in the history
Added Unix implementation of omrsig_set_single_async_signal_handler in
omrsignal.c.

Added a new macro OMR_IS_ONLY_ONE_BIT_SET in omrcomp.h to check if only
one bit is set in a non-zero value.

Signed-off-by: Babneet Singh <sbabneet@ca.ibm.com>
  • Loading branch information
babsingh committed Apr 27, 2018
1 parent 7953cbb commit f0dc570
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 5 deletions.
1 change: 1 addition & 0 deletions include_core/omrcomp.h
Expand Up @@ -575,6 +575,7 @@ typedef struct U_128 {
#define OMR_ARE_ANY_BITS_SET(value, bits) (0 != ((value) & (bits)))
#define OMR_ARE_ALL_BITS_SET(value, bits) ((bits) == ((value) & (bits)))
#define OMR_ARE_NO_BITS_SET(value, bits) (!OMR_ARE_ANY_BITS_SET(value, bits))
#define OMR_IS_ONLY_ONE_BIT_SET(value) (0 == (value & (value - 1)))

/* Workaround for gcc -Wunused-result, which was added in 4.5.4 */
#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)))
Expand Down
12 changes: 11 additions & 1 deletion port/common/omrport.tdf
Expand Up @@ -1053,4 +1053,14 @@ TraceEvent=Trc_PRT_sysinfo_cgroup_get_memlimit_unlimited Group=sysinfo Overhead=
TraceEvent=Trc_PRT_sysinfo_cgroup_get_memlimit Group=sysinfo Overhead=1 Level=1 NoEnv Template="omrsysinfo_cgroup_get_memlimit: memory limit is 0x%llx bytes"
TraceExit=Trc_PRT_sysinfo_cgroup_get_memlimit_Exit Group=sysinfo Overhead=1 Level=3 NoEnv Template="omrsysinfo_cgroup_get_memlimit exiting with rc=%d"

TraceEvent=Trc_PRT_signal_registerSignalHandlerWithOS_registeredHandler1 Group=signal Overhead=1 Level=1 NoEnv Template="registerSignalHandlerWithOS, registered signal handler with OS, portLibrarySignalNo=0x%X, unixSignalNo=0x%X, handler=%p, oldOSHandler=%p"
TraceEvent=Trc_PRT_signal_registerSignalHandlerWithOS_registeredHandler1 Group=signal Overhead=1 Level=1 NoEnv Template="registerSignalHandlerWithOS, registered signal handler with OS, portLibrarySignalNo=0x%X, unixSignalNo=0x%X, handler=%p, oldOSHandler=%p"

TraceEntry=Trc_PRT_signal_omrsig_set_single_async_signal_handler_entered Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: Entered, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X"
TraceExit-Exception=Trc_PRT_signal_omrsig_set_single_async_signal_handler_error_multiple_signal_flags_found Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: Exiting, error: more than one signal bit set in portlibSignalFlag=0x%X"
TraceEvent=Trc_PRT_signal_omrsig_set_single_async_signal_handler_will_not_set_handler_due_to_Xrs Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: will not set handler due to Xrs, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X"
TraceExit-Exception=Trc_PRT_signal_omrsig_set_single_async_signal_handler_exiting_did_nothing_possible_error Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: Exiting, possible error, rc=%d, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X"
TraceEvent=Trc_PRT_signal_omrsig_set_single_async_signal_handler_user_handler_removed Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: user handler removed, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X"
TraceEvent=Trc_PRT_signal_omrsig_set_single_async_signal_handler_user_handler_added_1 Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: user handler added_1, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X"
TraceEvent=Trc_PRT_signal_omrsig_set_single_async_signal_handler_user_handler_added_2 Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: user handler added_2, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X"
TraceExit=Trc_PRT_signal_omrsig_set_single_async_signal_handler_exiting Group=signal Overhead=1 Level=1 NoEnv Template="omrsig_set_single_async_signal_handler: Exiting, rc=%d, handler=%p, handler_arg=%p, portlibSignalFlag=0x%X, oldOSHandler=%p"

12 changes: 9 additions & 3 deletions port/common/omrsignal.c
Expand Up @@ -174,13 +174,19 @@ omrsig_set_async_signal_handler(struct OMRPortLibrary *portLibrary, omrsig_handl

/*
* @brief Similar to omrsig_set_async_signal_handler. Refer to omrsig_set_async_signal_handler's description above.
* Differences: 1) one omrsig_handler_fn handler is registered with a signal at any time instead of multiple handlers.
* 2) The address to the old signal handler function is stored in oldOSHandler.
* A new element is added to the asyncHandlerList for omrsig_handler_fn, and masterASynchSignalHandler is registered
* with the OS for the signal corresponding to the specified portlibSignalFlag. masterASynchSignalHandler invokes
* asyncHandlerList elements when a relevant signal is raised. If portlibSignalFlag is 0, then the asyncHandlerList
* entry corresponding to omrsig_handler_fn is removed, and related resources are freed. portlibSignalFlag can only
* have one signal flag set; otherwise, OMRPORT_SIG_ERROR is returned. One omrsig_handler_fn handler is registered
* with a signal at any time instead of multiple handlers. When associating a new omrsig_handler_fn with a signal,
* prior omrsig_handler_fn(s) are dissociated from the signal. The address of the old signal handler function is
* stored in oldOSHandler. This function supports all signals listed in OMRPORT_SIG_FLAG_SIGALLASYNC.
*
* @param[in] portLibrary The port library
* @param[in] handler the function to call if an asynchronous signal arrives
* @param[in] handler_arg the argument to handler
* @param[in] portlibSignalFlag port library signal flag
* @param[in] portlibSignalFlag a single port library signal flag, or 0 to remove the omrsig_handler_fn entry
* @param[out] oldOSHandler points to the old signal handler function
*
* @return 0 on success or non-zero on failure
Expand Down
94 changes: 93 additions & 1 deletion port/unix/omrsignal.c
Expand Up @@ -483,7 +483,99 @@ omrsig_set_async_signal_handler(struct OMRPortLibrary *portLibrary, omrsig_handl
int32_t
omrsig_set_single_async_signal_handler(struct OMRPortLibrary *portLibrary, omrsig_handler_fn handler, void *handler_arg, uint32_t portlibSignalFlag, void **oldOSHandler)
{
return OMRPORT_SIG_ERROR;
uint32_t rc = 0;
J9UnixAsyncHandlerRecord *cursor = NULL;
J9UnixAsyncHandlerRecord **previousLink = NULL;
BOOLEAN foundHandler = FALSE;

Trc_PRT_signal_omrsig_set_single_async_signal_handler_entered(handler, handler_arg, portlibSignalFlag);

if (0 != portlibSignalFlag) {
/* For non-zero portlibSignalFlag, check if only one signal bit is set. Otherwise, fail. */
if (!OMR_IS_ONLY_ONE_BIT_SET(portlibSignalFlag)) {
Trc_PRT_signal_omrsig_set_single_async_signal_handler_error_multiple_signal_flags_found(portlibSignalFlag);
return OMRPORT_SIG_ERROR;
}
}

omrthread_monitor_enter(masterHandlerMonitor);

if (OMR_ARE_ANY_BITS_SET(signalOptionsGlobal, OMRPORT_SIG_OPTIONS_REDUCED_SIGNALS_ASYNCHRONOUS)) {
/* -Xrs was set, we can't protect against any signals, do not install any handlers except SIGXFSZ*/
if (OMR_ARE_ANY_BITS_SET(portlibSignalFlag, OMRPORT_SIG_FLAG_SIGXFSZ) && OMR_ARE_ANY_BITS_SET(signalOptionsGlobal, OMRPORT_SIG_OPTIONS_SIGXFSZ)) {
rc = registerMasterHandlers(portLibrary, OMRPORT_SIG_FLAG_SIGXFSZ, OMRPORT_SIG_FLAG_SIGALLASYNC, oldOSHandler);
} else {
Trc_PRT_signal_omrsig_set_single_async_signal_handler_will_not_set_handler_due_to_Xrs(handler, handler_arg, portlibSignalFlag);
rc = OMRPORT_SIG_ERROR;
}
} else {
rc = registerMasterHandlers(portLibrary, portlibSignalFlag, OMRPORT_SIG_FLAG_SIGALLASYNC, oldOSHandler);
}
omrthread_monitor_exit(masterHandlerMonitor);

if (0 != rc) {
Trc_PRT_signal_omrsig_set_single_async_signal_handler_exiting_did_nothing_possible_error(rc, handler, handler_arg, portlibSignalFlag);
return rc;
}

omrthread_monitor_enter(asyncMonitor);

/* wait until no signals are being reported */
while (asyncThreadCount > 0) {
omrthread_monitor_wait(asyncMonitor);
}

/* is this handler already registered? */
previousLink = &asyncHandlerList;
cursor = asyncHandlerList;

while (NULL != cursor) {
if (cursor->portLib == portLibrary) {
if ((cursor->handler == handler) && (cursor->handler_arg == handler_arg)) {
foundHandler = TRUE;
if (0 == portlibSignalFlag) {
/* Remove the listener. Remove this handler record.
* NOTE: masterHandlers get removed at omrsignal shutdown
*/
*previousLink = cursor->next;
portLibrary->mem_free_memory(portLibrary, cursor);
Trc_PRT_signal_omrsig_set_single_async_signal_handler_user_handler_removed(handler, handler_arg, portlibSignalFlag);
break;
} else {
/* Update the listener with the new portlibSignalFlag */
Trc_PRT_signal_omrsig_set_single_async_signal_handler_user_handler_added_1(handler, handler_arg, portlibSignalFlag);
cursor->flags |= portlibSignalFlag;
}
} else {
/* Unset the portlibSignalFlag for other handlers. One signal must be associated to only one handler. */
cursor->flags &= ~portlibSignalFlag;
}
}
previousLink = &cursor->next;
cursor = cursor->next;
}

if (!foundHandler && (0 != portlibSignalFlag)) {
J9UnixAsyncHandlerRecord *record = portLibrary->mem_allocate_memory(portLibrary, sizeof(*record), OMR_GET_CALLSITE(), OMRMEM_CATEGORY_PORT_LIBRARY);
if (NULL == record) {
rc = 1;
} else {
record->portLib = portLibrary;
record->handler = handler;
record->handler_arg = handler_arg;
record->flags = portlibSignalFlag;
record->next = NULL;

/* add the new record to the end of the list */
Trc_PRT_signal_omrsig_set_single_async_signal_handler_user_handler_added_2(handler, handler_arg, portlibSignalFlag);
*previousLink = record;
}
}

omrthread_monitor_exit(asyncMonitor);

Trc_PRT_signal_omrsig_set_single_async_signal_handler_exiting(rc, handler, handler_arg, portlibSignalFlag, *oldOSHandler);
return rc;
}

uint32_t
Expand Down

0 comments on commit f0dc570

Please sign in to comment.