diff --git a/include/lwp.h b/include/lwp.h index 1a96322c..e115ad70 100644 --- a/include/lwp.h +++ b/include/lwp.h @@ -28,7 +28,7 @@ * lwp.h -- prototypes and structures for lightweight processes * * Known contributors to this file: - * Markus Armbruster, 2004-2013 + * Markus Armbruster, 2004-2020 * Ron Koenderink, 2007-2009 */ @@ -41,7 +41,6 @@ #ifndef LWP_H #define LWP_H -#include #include #define LWP_STACKCHECK 0x1 @@ -55,7 +54,7 @@ struct lwp_rwlock; #define LWP_MAX_PRIO 8 -struct lwpProc *lwpInitSystem(int prio, void **ctxp, int flags, sigset_t *); +struct lwpProc *lwpInitSystem(int prio, void **ctxp, int flags, int[]); struct lwpProc *lwpCreate(int prio, void (*)(void *), int size, int flags, char *name, int argc, char **argv, void *ud); @@ -65,7 +64,7 @@ void lwpYield(void); int lwpSleepFd(int fd, int flags, struct timeval *timeout); int lwpSleepUntil(time_t until); void lwpWakeup(struct lwpProc *); -int lwpSigWait(sigset_t *set, int *sig); +int lwpSigWait(int *sig); void *lwpGetUD(struct lwpProc *); void lwpSetUD(struct lwpProc *, char *ud); int lwpSetPriority(int prio); diff --git a/src/lib/empthread/lwp.c b/src/lib/empthread/lwp.c index 376fc622..d26eae7c 100644 --- a/src/lib/empthread/lwp.c +++ b/src/lib/empthread/lwp.c @@ -28,7 +28,7 @@ * * Known contributors to this file: * Sasha Mikheev - * Markus Armbruster, 2006-2009 + * Markus Armbruster, 2006-2020 */ #include @@ -42,23 +42,16 @@ /* Flags that were passed to empth_init() */ static int empth_flags; - int empth_init(void **ctx, int flags) { - sigset_t set; - + static int sig[] = { SIGHUP, SIGINT, SIGTERM, 0 }; empth_flags = flags; empth_init_signals(); - sigemptyset(&set); - sigaddset(&set, SIGHUP); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGTERM); - lwpInitSystem(1, ctx, flags, &set); + lwpInitSystem(1, ctx, flags, sig); return 0; } - empth_t * empth_create(void (*entry)(void *), int size, int flags, char *name, void *ud) @@ -124,17 +117,12 @@ empth_sleep(time_t until) int empth_wait_for_signal(void) { - sigset_t set; int sig, err; time_t now; ef_make_stale(); - sigemptyset(&set); - sigaddset(&set, SIGHUP); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGTERM); for (;;) { - err = lwpSigWait(&set, &sig); + err = lwpSigWait(&sig); if (CANT_HAPPEN(err)) { time(&now); lwpSleepUntil(now + 60); diff --git a/src/lib/lwp/lwp.c b/src/lib/lwp/lwp.c index 803aff09..a7d33b98 100644 --- a/src/lib/lwp/lwp.c +++ b/src/lib/lwp/lwp.c @@ -28,7 +28,7 @@ * lwp.c: lightweight process creation, destruction and manipulation * * Known contributors to this file: - * Markus Armbruster, 2004-2017 + * Markus Armbruster, 2004-2020 */ #include @@ -296,7 +296,7 @@ lwpSetPriority(int new) * initialise the coroutine structures */ struct lwpProc * -lwpInitSystem(int pri, void **ctxptr, int flags, sigset_t *waitset) +lwpInitSystem(int pri, void **ctxptr, int flags, int sig[]) { struct lwpQueue *q; int i, *stack, marker; @@ -323,7 +323,7 @@ lwpInitSystem(int pri, void **ctxptr, int flags, sigset_t *waitset) for (i = LWP_MAX_PRIO, q = LwpSchedQ; i--; q++) q->head = q->tail = NULL; LwpDeadQ.head = LwpDeadQ.tail = NULL; - lwpInitSigWait(waitset); + lwpInitSigWait(sig); /* must be lower in priority than us for this to work right */ sel = lwpCreate(0, lwpSelect, 65536, flags, "EventHandler", 0, NULL, NULL); diff --git a/src/lib/lwp/lwpint.h b/src/lib/lwp/lwpint.h index cca3eac7..7a317140 100644 --- a/src/lib/lwp/lwpint.h +++ b/src/lib/lwp/lwpint.h @@ -28,13 +28,12 @@ * lwpint.h: lwp internal structures * * Known contributors to this file: - * Markus Armbruster, 2004-2009 + * Markus Armbruster, 2004-2020 */ #ifndef LWPINT_H #define LWPINT_H -#include #include #include @@ -82,7 +81,7 @@ void lwpEntryPoint(void); void lwpInitSelect(struct lwpProc *); void lwpWakeupSleep(void); void lwpSelect(void *); -void lwpInitSigWait(sigset_t *); +void lwpInitSigWait(int[]); void lwpSigWakeup(void); void lwpStatus(struct lwpProc *, char *, ...) ATTRIBUTE((format (printf, 2, 3))); diff --git a/src/lib/lwp/sig.c b/src/lib/lwp/sig.c index 62d19728..41d1c31e 100644 --- a/src/lib/lwp/sig.c +++ b/src/lib/lwp/sig.c @@ -34,20 +34,26 @@ #include #include +#include #include #include "lwp.h" #include "lwpint.h" /* - * Signals caught so far. - * Access only with signals blocked! + * Awaited signal numbers, terminated with 0. */ -static sigset_t LwpSigCaught; +static int *LwpAwaitedSig; /* - * LwpSigCaught changed since last + * Pending awaited signals. + * Access only with signals blocked! */ -static sig_atomic_t LwpSigCheck; +static volatile int *LwpSigCaught; + +/* + * Is there anything in LwpSigCaught[]? + */ +static volatile sig_atomic_t LwpSigCheck; /* The thread waiting for signals in lwpSigWait() */ static struct lwpProc *LwpSigWaiter; @@ -55,80 +61,96 @@ static struct lwpProc *LwpSigWaiter; static void lwpCatchAwaitedSig(int); /* - * Initialize waiting for signals in @set. + * Initialize waiting for signals in @sig[]. + * @sig[] contains signal numbers, terminated with 0. It must have + * static storage duration. */ void -lwpInitSigWait(sigset_t *set) +lwpInitSigWait(int sig[]) { struct sigaction act; int i; - sigemptyset(&LwpSigCaught); + LwpAwaitedSig = sig; act.sa_flags = 0; - act.sa_mask = *set; act.sa_handler = lwpCatchAwaitedSig; - for (i = 0; i < NSIG; i++) { - if (sigismember(set, i) > 0) - sigaction(i, &act, NULL); - } + sigemptyset(&act.sa_mask); + for (i = 0; sig[i]; i++) + sigaddset(&act.sa_mask, sig[i]); + + LwpSigCaught = calloc(i, sizeof(*LwpSigCaught)); + + for (i = 0; sig[i]; i++) + sigaction(sig[i], &act, NULL); } +/* + * Signal handler for awaited signals. + * Set @LwpSigCaught[] for @sig, and set @LwpSigCheck. + * Not reentrant; lwpInitSigWait() guards. + */ static void lwpCatchAwaitedSig(int sig) { - sigaddset(&LwpSigCaught, sig); + int i; + + for (i = 0; LwpAwaitedSig[i]; i++) { + if (sig == LwpAwaitedSig[i]) + LwpSigCaught[i] = 1; + } LwpSigCheck = 1; } /* - * Test whether a signal from @set has been caught. - * If yes, delete that signal from the set of caught signals, and + * Test whether an awaited signal is pending. + * If yes, remove that signal from the set of pending signals, and * return its number. * Else return 0. */ static int -lwpGetSig(sigset_t *set) +lwpGetSig(void) { - sigset_t save; - int i, j; + int ret = 0; + sigset_t set, save; + int i; - sigprocmask(SIG_BLOCK, set, &save); + sigemptyset(&set); + for (i = 0; LwpAwaitedSig[i]; i++) + sigaddset(&set, LwpAwaitedSig[i]); + sigprocmask(SIG_BLOCK, &set, &save); - for (i = NSIG - 1; i > 0; i--) { - if (sigismember(set, i) > 0 && sigismember(&LwpSigCaught, i) > 0) { - lwpStatus(LwpCurrent, "Got awaited signal %d", i); - sigdelset(&LwpSigCaught, i); - break; + for (i = 0; LwpAwaitedSig[i]; i++) { + if (LwpSigCaught[i]) { + lwpStatus(LwpCurrent, "Got awaited signal %d", LwpSigCaught[i]); + ret = LwpAwaitedSig[i]; + LwpSigCaught[i] = 0; } } - for (j = i; - sigismember(set, i) > 0 && sigismember(&LwpSigCaught, i) > 0; - j--) - ; - if (!j) + for (; LwpAwaitedSig[i] && LwpSigCaught[i]; i++) ; + if (!LwpSigCaught[i]) LwpSigCheck = 0; sigprocmask(SIG_SETMASK, &save, NULL); - return i; + return ret; } /* - * Wait until a signal from @set arrives. + * Wait until one of the signals passed to lwpInitSigWait() arrives. * Assign its number to *@sig and return 0. * If another thread is already waiting for signals, return EBUSY * without waiting. */ int -lwpSigWait(sigset_t *set, int *sig) +lwpSigWait(int *sig) { int res; if (LwpSigWaiter) return EBUSY; for (;;) { - res = lwpGetSig(set); + res = lwpGetSig(); if (res > 0) break; lwpStatus(LwpCurrent, "Waiting for signals");