Make sigmux_init reinitialize its signal handler every time
Summary: Bailing out early works fine but prevents us from reinstalling signal handlers when we really want to. Perform non-idempotent alloc-inits with compare-exchange atomics instead, and reinstall the signal handler every time.
@@ -420,15 +420,6 @@ sigmux_handle_signal_1(
SIGMUX_HANDLE_SIGNAL_INVOKE_DEFAULT ));
}
-static struct sigaction*
-allocate_sigaction(struct sigaction** sap)
-{
- if (*sap == NULL) {
- *sap = calloc(1, sizeof (**sap));
- }
- return *sap;
-}
-
int
sigmux_init(int signum)
{
@@ -448,19 +439,39 @@ sigmux_init(int signum)
goto out;
}
- if (ismem == 0) {
-
- struct sigaction* orig_sigact =
- allocate_sigaction(&sigmux_global.orig_sigact[signum]);
+ struct sigaction* temp = NULL;
+ struct sigaction* orig_sigact = calloc(1, sizeof(struct sigaction));
if (orig_sigact == NULL) {
goto out;
}
+ if (!__atomic_compare_exchange_n(
+ &sigmux_global.orig_sigact[signum],
+ &temp,
+ orig_sigact,
+ false,
+ __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST)) {
+ free(orig_sigact);
+ orig_sigact = temp;
+ }
// Pre-allocate spare memory for sigmux_sigaction, since it isn't
// allowed to fail with ENOMEM.
- if (allocate_sigaction(&sigmux_global.alt_sigact[signum]) == NULL) {
+ temp = NULL;
+ struct sigaction* alt_sigact = calloc(1, sizeof(struct sigaction));
+ if (alt_sigact == NULL) {
goto out;
}
+ if (!__atomic_compare_exchange_n(
+ &sigmux_global.alt_sigact[signum],
+ &temp,
+ alt_sigact,
+ false,
+ __ATOMIC_SEQ_CST,
+ __ATOMIC_SEQ_CST)) {
+ free(alt_sigact);
+ alt_sigact = temp;
+ }
memset(&newact, 0, sizeof (newact));
newact.sa_sigaction = sigmux_handle_signal_1;
@@ -472,7 +483,6 @@ sigmux_init(int signum)
sigmux_sigaddset(&sigmux_global.initsig, signum);
__atomic_signal_fence(__ATOMIC_SEQ_CST);
sigmux_gdbhook_on_signal_seized();
- }
ret = 0;
