PR/56254: RVP: Don't call non-async-signal-safe functions from signal handlers.

Establish a non-restart signal handler to avoid blocking in long I/Os.
This commit is contained in:
christos 2022-02-11 21:15:25 +00:00
parent ab67b1ab7c
commit c3c5452ebd
1 changed files with 30 additions and 13 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: script.c,v 1.30 2022/01/20 19:49:51 christos Exp $ */ /* $NetBSD: script.c,v 1.31 2022/02/11 21:15:25 christos Exp $ */
/* /*
* Copyright (c) 1980, 1992, 1993 * Copyright (c) 1980, 1992, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1992, 1993\
#if 0 #if 0
static char sccsid[] = "@(#)script.c 8.1 (Berkeley) 6/6/93"; static char sccsid[] = "@(#)script.c 8.1 (Berkeley) 6/6/93";
#endif #endif
__RCSID("$NetBSD: script.c,v 1.30 2022/01/20 19:49:51 christos Exp $"); __RCSID("$NetBSD: script.c,v 1.31 2022/02/11 21:15:25 christos Exp $");
#endif /* not lint */ #endif /* not lint */
#include <sys/types.h> #include <sys/types.h>
@ -81,6 +81,8 @@ static int usesleep, rawout;
static int quiet, flush; static int quiet, flush;
static const char *fname; static const char *fname;
static volatile sig_atomic_t die = 0; /* exit if 1 */
static int cstat = EXIT_SUCCESS; /* cmd. exit status */
static int eflag; static int eflag;
static int isterm; static int isterm;
static struct termios tt; static struct termios tt;
@ -88,6 +90,7 @@ static struct termios tt;
__dead static void done(int); __dead static void done(int);
__dead static void doshell(const char *); __dead static void doshell(const char *);
__dead static void fail(void); __dead static void fail(void);
static sig_t xsignal(int, sig_t);
static void dooutput(void); static void dooutput(void);
static void finish(int); static void finish(int);
static void scriptflush(int); static void scriptflush(int);
@ -182,7 +185,7 @@ main(int argc, char *argv[])
(void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
} }
(void)signal(SIGCHLD, finish); (void)xsignal(SIGCHLD, finish);
child = fork(); child = fork();
if (child == -1) { if (child == -1) {
warn("fork"); warn("fork");
@ -202,35 +205,49 @@ main(int argc, char *argv[])
if (!rawout) if (!rawout)
(void)fclose(fscript); (void)fclose(fscript);
while ((scc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) { while (!die && (scc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) {
cc = (size_t)scc; cc = (size_t)scc;
if (rawout) if (rawout)
record(fscript, ibuf, cc, 'i'); record(fscript, ibuf, cc, 'i');
(void)write(master, ibuf, cc); (void)write(master, ibuf, cc);
} }
finish(-1); done(cstat);
}
/**
* wrapper around sigaction() because we want POSIX semantics:
* no auto-restarting of interrupted slow syscalls.
*/
static sig_t
xsignal(int signo, sig_t handler)
{
struct sigaction sa, osa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
if (sigaction(signo, &sa, &osa) == -1)
return SIG_ERR;
return osa.sa_handler;
} }
static void static void
finish(int signo) finish(int signo)
{ {
int die, pid, status, cstat; int pid, status;
die = 0;
while ((pid = wait(&status)) > 0) while ((pid = wait(&status)) > 0)
if (pid == child) { if (pid == child) {
cstat = status; cstat = status;
die = 1; die = 1;
} }
if (!die)
return;
if (!eflag) if (!eflag)
done(EXIT_SUCCESS); cstat = EXIT_SUCCESS;
else if (WIFEXITED(cstat)) else if (WIFEXITED(cstat))
done(WEXITSTATUS(cstat)); cstat = WEXITSTATUS(cstat);
else else
done(128 + WTERMSIG(cstat)); cstat = 128 + WTERMSIG(cstat);
} }
static void static void
@ -268,7 +285,7 @@ dooutput(void)
if (flush) if (flush)
(void)fflush(fscript); (void)fflush(fscript);
} }
finish(-1); done(cstat);
} }
static void static void