Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/script PR/56254: RVP: Don't call non-async-signal-sa...



details:   https://anonhg.NetBSD.org/src/rev/be25bcaf87ee
branches:  trunk
changeset: 361123:be25bcaf87ee
user:      christos <christos%NetBSD.org@localhost>
date:      Fri Feb 11 21:15:25 2022 +0000

description:
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.

diffstat:

 usr.bin/script/script.c |  43 ++++++++++++++++++++++++++++++-------------
 1 files changed, 30 insertions(+), 13 deletions(-)

diffs (112 lines):

diff -r bc35652dea75 -r be25bcaf87ee usr.bin/script/script.c
--- a/usr.bin/script/script.c   Fri Feb 11 17:53:28 2022 +0000
+++ b/usr.bin/script/script.c   Fri Feb 11 21:15:25 2022 +0000
@@ -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
@@ -39,7 +39,7 @@
 #if 0
 static char sccsid[] = "@(#)script.c   8.1 (Berkeley) 6/6/93";
 #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 */
 
 #include <sys/types.h>
@@ -81,6 +81,8 @@
 static int     quiet, flush;
 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     isterm;
 static struct  termios tt;
@@ -88,6 +90,7 @@
 __dead static void     done(int);
 __dead static void     doshell(const char *);
 __dead static void     fail(void);
+static sig_t   xsignal(int, sig_t);
 static void    dooutput(void);
 static void    finish(int);
 static void    scriptflush(int);
@@ -182,7 +185,7 @@
                (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
        }
 
-       (void)signal(SIGCHLD, finish);
+       (void)xsignal(SIGCHLD, finish);
        child = fork();
        if (child == -1) {
                warn("fork");
@@ -202,35 +205,49 @@
 
        if (!rawout)
                (void)fclose(fscript);
-       while ((scc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) {
+       while (!die && (scc = read(STDIN_FILENO, ibuf, BUFSIZ)) > 0) {
                cc = (size_t)scc;
                if (rawout)
                        record(fscript, ibuf, cc, 'i');
                (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
 finish(int signo)
 {
-       int die, pid, status, cstat;
+       int pid, status;
 
-       die = 0;
        while ((pid = wait(&status)) > 0)
                if (pid == child) {
                        cstat = status;
                        die = 1;
                }
 
-       if (!die)
-               return;
        if (!eflag)
-               done(EXIT_SUCCESS);
+               cstat = EXIT_SUCCESS;
        else if (WIFEXITED(cstat))
-               done(WEXITSTATUS(cstat));
+               cstat = WEXITSTATUS(cstat);
        else
-               done(128 + WTERMSIG(cstat));
+               cstat = 128 + WTERMSIG(cstat);
 }
 
 static void
@@ -268,7 +285,7 @@
                if (flush)
                        (void)fflush(fscript);
        }
-       finish(-1);
+       done(cstat);
 }
 
 static void



Home | Main Index | Thread Index | Old Index