aboutsummaryrefslogtreecommitdiffstats
path: root/src/signals.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/signals.c')
-rw-r--r--src/signals.c90
1 files changed, 82 insertions, 8 deletions
diff --git a/src/signals.c b/src/signals.c
index 390d684..cd23773 100644
--- a/src/signals.c
+++ b/src/signals.c
@@ -22,6 +22,7 @@
volatile sig_atomic_t exiting = 0;
volatile sig_atomic_t disable = 0;
+volatile enum signals signals = 0;
/**
@@ -40,19 +41,19 @@ sigexit(int signo)
}
+#ifndef WINDOWS
+
/**
* Signal handler for disable signal (SIGUSR1)
*
* @param signo The received signal
*/
-#ifndef WINDOWS
static void
sigdisable(int signo)
{
disable = 1;
(void) signo;
}
-#endif
/**
@@ -61,7 +62,6 @@ sigdisable(int signo)
*
* @param signo The received signal
*/
-#ifndef WINDOWS
static void
sigalrm(int signo)
{
@@ -70,6 +70,71 @@ sigalrm(int signo)
exiting = 1;
alarm(1U);
}
+
+
+/**
+ * Signal handler for SIGUSR2
+ *
+ * @param signo The received signal
+ * @param info The received signal data
+ * @param uctx Interrupted stack context
+ */
+static void
+sigipc(int signo, siginfo_t *info, void *uctx)
+{
+ int set, mask;
+ sigset_t sigusr2_mask;
+
+ (void) signo;
+ (void) uctx;
+
+ if (info->si_code != SI_QUEUE)
+ return;
+
+ switch (info->si_value.sival_int) {
+ case 1:
+ case 2:
+ mask = 3 << 1;
+ break;
+
+ case 5:
+ case 6:
+ mask = 3 << 5;
+ break;
+
+ case 7:
+ case 8:
+ mask = 3 << 7;
+ break;
+
+ case 11:
+ case 12:
+ mask = 3 << 11;
+ break;
+
+ case 0:
+ case 3:
+ case 4:
+ case 9:
+ case 10:
+ mask = 0;
+ break;
+
+ default:
+ return;
+ }
+
+ signals |= set = 1 << info->si_value.sival_int;
+ signals &= ~mask | set;
+
+ if (set == SIGNAL_ORDER_BARRIER) {
+ sigemptyset(&sigusr2_mask);
+ sigaddset(&sigusr2_mask, SIGUSR2);
+ if (sigprocmask(SIG_BLOCK, &sigusr2_mask, NULL))
+ eprintf("sigprocmask:");
+ }
+}
+
#endif
@@ -89,23 +154,32 @@ install_signal_handlers(void)
memset(&sigact, 0, sizeof(sigact));
sigemptyset(&sigset);
sigact.sa_mask = sigset;
- sigact.sa_flags = 0;
+
+ sigact.sa_flags = SA_NODEFER;
sigact.sa_handler = &sigexit;
if (sigaction(SIGINT, &sigact, NULL))
- eprintf("sigaction SIGINT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:");
+ eprintf("sigaction SIGINT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:");
if (sigaction(SIGTERM, &sigact, NULL))
- eprintf("sigaction SIGTERM &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:");
+ eprintf("sigaction SIGTERM &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:");
if (sigaction(SIGQUIT, &sigact, NULL))
- eprintf("sigaction SIGQUIT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:");
+ eprintf("sigaction SIGQUIT &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:");
sigact.sa_handler = &sigdisable;
if (sigaction(SIGUSR1, &sigact, NULL))
- eprintf("sigaction SIGUSR1 &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=0} NULL:");
+ eprintf("sigaction SIGUSR1 &{.sa_handler=<function pointer>, .sa_mask={}, .sa_flags=SA_NODEFER} NULL:");
+
+ sigact.sa_flags = 0;
sigact.sa_handler = SIG_IGN; /* cause child processes (hooks) to be reaped automatically */
if (sigaction(SIGCHLD, &sigact, NULL))
eprintf("sigaction SIGCHLD &{.sa_handler=SIG_IGN, .sa_mask={}, .sa_flags=0} NULL:");
+
+ sigact.sa_flags = SA_SIGINFO;
+
+ sigact.sa_sigaction = &sigipc;
+ if (sigaction(SIGUSR2, &sigact, NULL))
+ eprintf("sigaction SIGUSR2 &{.sa_sigaction=<function pointer>, .sa_mask={}, .sa_flags=SA_SIGINFO} NULL:");
#endif
}