scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 93e07bb34a825734d760971f811ac43868fd8c48
parent e19109cd35b8d64480c74389b8faaedf5af9b0ed
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date:   Tue, 28 Oct 2025 21:10:31 +0100

scc-make: Avoid signal race conditions

Expecting ait to be interrupted by a signal is too risky
and it is very easy to be caught by race conditions. The
best option is to kill in the snal handler and lock signals
until we are ready to deal with them.

Diffstat:
Msrc/cmd/scc-make/main.c | 1+
Msrc/cmd/scc-make/make.h | 1+
Msrc/cmd/scc-make/posix.c | 35+++++++++++++++++++++++++++++------
3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/src/cmd/scc-make/main.c b/src/cmd/scc-make/main.c @@ -90,6 +90,7 @@ estrdup(char *s) void sighandler(int signo) { + killchild(); stop = signo; } diff --git a/src/cmd/scc-make/make.h b/src/cmd/scc-make/make.h @@ -67,6 +67,7 @@ extern char *getmacro(char *); extern void setmacro(char *, char *, int, int); /* system depdendant */ +extern void killchild(void); extern time_t stamp(char *); extern int launch(char *, int); extern int putenv(char *); diff --git a/src/cmd/scc-make/posix.c b/src/cmd/scc-make/posix.c @@ -12,6 +12,17 @@ #include "make.h" + +static volatile pid_t pid; + +void +killchild(void) +{ + if (pid != 0) + kill(pid, SIGTERM); + pid = 0; +} + int is_dir(char *fname) { @@ -49,14 +60,13 @@ int launch(char *cmd, int ignore) { int st; - pid_t pid; + sigset_t new, old; char *name, *shell; char *args[] = {NULL, "-ec" , cmd, NULL}; static int initsignals; extern char **environ; extern void sighandler(int); - if (!initsignals) { struct sigaction act = { .sa_handler = sighandler @@ -70,10 +80,25 @@ launch(char *cmd, int ignore) initsignals = 1; } + sigfillset(&new); + sigprocmask(SIG_BLOCK, &new, &old); + if (stop) + goto unblock; + switch (pid = fork()) { case -1: + perror("make"); + unblock: + sigprocmask(SIG_SETMASK, &old, NULL); return -1; case 0: + signal(SIGINT, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + + sigprocmask(SIG_SETMASK, &old, NULL); + shell = getmacro("SHELL"); if (ignore) @@ -86,10 +111,8 @@ launch(char *cmd, int ignore) execve(shell, args, environ); _exit(127); default: - if (wait(&st) < 0) { - kill(pid, SIGTERM); - wait(&st); - } + sigprocmask(SIG_SETMASK, &old, NULL); + wait(&st); return st; }