commit f7f69125cf296bfd50a483c976f0991ec6e9ffe1
parent f8d39b2329be259e46efd019091e6061de5fbe4b
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date: Wed, 31 Dec 2025 15:31:21 +0100
make: Synchronize with scc
Scc fixed a race condition hapenning while forking and execing the command
and receiving a signal that could keep make waiting forever. Signals
are correctly masked now to avoid this problems.
Diffstat:
4 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/make/main.c b/make/main.c
@@ -90,6 +90,7 @@ estrdup(char *s)
void
sighandler(int signo)
{
+ killchild();
stop = signo;
}
diff --git a/make/make.h b/make/make.h
@@ -43,35 +43,36 @@ struct target {
struct target *next;
};
-extern void *emalloc(size_t);
-extern void *erealloc(void *, size_t);
-extern char *estrdup(char *);
-
-extern void dumprules(void);
-extern void dumpmacros(void);
-
-extern char *expandstring(char *, Target *, struct loc *);
-extern void addtarget(char *, int);
-extern void inject(char *);
-extern int build(char *);
-extern int hash(char *);
-extern int parse(char *);
-extern void debug(char *, ...);
-extern void error(char *, ...);
-extern void warning(char *, ...);
-extern void adddep(char *, char *);
-extern void addrule(char *, struct action *, int);
-extern void freeloc(struct loc *);
-
-extern char *getmacro(char *);
-extern void setmacro(char *, char *, int, int);
+void *emalloc(size_t);
+void *erealloc(void *, size_t);
+char *estrdup(char *);
+
+void dumprules(void);
+void dumpmacros(void);
+
+char *expandstring(char *, Target *, struct loc *);
+void addtarget(char *, int);
+void inject(char *);
+int build(char *);
+int hash(char *);
+int parse(char *);
+void debug(char *, ...);
+void error(char *, ...);
+void warning(char *, ...);
+void adddep(char *, char *);
+void addrule(char *, struct action *, int);
+void freeloc(struct loc *);
+
+char *getmacro(char *);
+void setmacro(char *, char *, int, int);
/* system depdendant */
-extern time_t stamp(char *);
-extern int launch(char *, int);
-extern int putenv(char *);
-extern void exportvar(char *, char *);
-extern int is_dir(char *);
+void killchild(void);
+time_t stamp(char *);
+int launch(char *, int);
+int putenv(char *);
+void exportvar(char *, char *);
+int is_dir(char *);
/* main.c */
extern int kflag, dflag, nflag, iflag, sflag;
diff --git a/make/posix.c b/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;
}
diff --git a/make/rules.c b/make/rules.c
@@ -62,10 +62,11 @@ lookup(char *name)
static void
cleanup(Target *tp)
{
- int precious;
+ int sig, precious;
Target *p, **q;
- printf("make: signal %d arrived\n", stop);
+ sig = stop;
+ printf("make: signal %d arrived\n", sig);
precious = 0;
p = lookup(".PRECIOUS");
@@ -81,8 +82,8 @@ cleanup(Target *tp)
remove(tp->name);
}
- signal(stop, SIG_DFL);
- raise(stop);
+ signal(sig, SIG_DFL);
+ raise(sig);
}
static int