Explicitly initialize sigaction::sa_mask members with sigemptyset(3)

Not doing so before calling sigaction(3) is "undefined" according to
POSIX[1]:

> Applications shall call either sigemptyset() or sigfillset() at least
> once for each object of type sigset_t prior to any other use of that
> object. If such an object is not initialized in this way, but is
> nonetheless supplied as an argument to any of pthread_sigmask(),
> sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(),
> sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or
> sigwaitinfo(), the results are undefined.

The use of designated initializers means that sa_mask members were
still being initialized, but sigset_t is an opaque type and implicit
initialization doesn't necessarily produce the same results as using
sigemptyset(3) (although it typically does on most implementations).

[1]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html
This commit is contained in:
Craig Barnes 2022-02-12 12:04:57 +00:00
parent d34c8007f1
commit 23cf80667a
6 changed files with 16 additions and 6 deletions

View file

@ -455,7 +455,8 @@ main(int argc, char *const *argv)
}
}
const struct sigaction sa = {.sa_handler = &sig_handler};
struct sigaction sa = {.sa_handler = &sig_handler};
sigemptyset(&sa.sa_mask);
if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0) {
LOG_ERRNO("failed to register signal handlers");
goto err;

2
fdm.c
View file

@ -352,6 +352,7 @@ fdm_signal_add(struct fdm *fdm, int signo, fdm_signal_handler_t handler, void *d
}
struct sigaction action = {.sa_handler = &signal_handler};
sigemptyset(&action.sa_mask);
if (sigaction(signo, &action, NULL) < 0) {
LOG_ERRNO("failed to set signal handler for signal %d", signo);
sigprocmask(SIG_SETMASK, &original, NULL);
@ -371,6 +372,7 @@ fdm_signal_del(struct fdm *fdm, int signo)
return false;
struct sigaction action = {.sa_handler = SIG_DFL};
sigemptyset(&action.sa_mask);
if (sigaction(signo, &action, NULL) < 0) {
LOG_ERRNO("failed to restore signal handler for signal %d", signo);
return false;

3
main.c
View file

@ -625,7 +625,8 @@ main(int argc, char *const *argv)
goto out;
}
const struct sigaction sig_ign = {.sa_handler = SIG_IGN};
struct sigaction sig_ign = {.sa_handler = SIG_IGN};
sigemptyset(&sig_ign.sa_mask);
if (sigaction(SIGHUP, &sig_ign, NULL) < 0 ||
sigaction(SIGPIPE, &sig_ign, NULL) < 0)
{

View file

@ -275,7 +275,8 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
}
/* Restore signal mask, and SIG_IGN'd signals */
const struct sigaction dfl = {.sa_handler = SIG_DFL};
struct sigaction dfl = {.sa_handler = SIG_DFL};
sigemptyset(&dfl.sa_mask);
sigset_t mask;
sigemptyset(&mask);

View file

@ -45,7 +45,9 @@ spawn(struct reaper *reaper, const char *cwd, char *const argv[],
goto child_err;
/* Restore ignored (SIG_IGN) signals */
if (sigaction(SIGHUP, &(struct sigaction){.sa_handler = SIG_DFL}, NULL) < 0)
struct sigaction dfl = {.sa_handler = SIG_DFL};
sigemptyset(&dfl.sa_mask);
if (sigaction(SIGHUP, &dfl, NULL) < 0)
goto child_err;
if (cwd != NULL && chdir(cwd) < 0) {

View file

@ -1716,7 +1716,9 @@ term_destroy(struct terminal *term)
* course only applies to a 'foot --server' instance, where
* there might be other terminals running.
*/
sigaction(SIGALRM, &(const struct sigaction){.sa_handler = &sig_alarm}, NULL);
struct sigaction action = {.sa_handler = &sig_alarm};
sigemptyset(&action.sa_mask);
sigaction(SIGALRM, &action, NULL);
alarm(60);
while (true) {
@ -1740,7 +1742,8 @@ term_destroy(struct terminal *term)
/* Cancel alarm */
alarm(0);
sigaction(SIGALRM, &(const struct sigaction){.sa_handler = SIG_DFL}, NULL);
action.sa_handler = SIG_DFL;
sigaction(SIGALRM, &action, NULL);
}
ret = EXIT_FAILURE;