]> granicus.if.org Git - strace/commitdiff
Do not reset SIGCHLD handler in tracees to SIG_DFL
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 27 May 2017 15:58:54 +0000 (15:58 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 27 May 2017 17:59:44 +0000 (17:59 +0000)
While strace resets SIGCHLD handler to the default action so that
waitpid definitely works without losing track of children, tracees
should not inherit this change.

* strace.c (struct exec_params): Add child_sa field.
(init): When setting SIGCHLD handler to SIG_DFL, save the old handler.
(exec_or_die): Restore SIGCHLD handler if it was different from SIG_DFL
at startup.
* NEWS: Mention this change.

NEWS
strace.c

diff --git a/NEWS b/NEWS
index 80479a15b7481f6585c8c80dd4e338f3d5359414..5866e69ad285ecad238a64bee1413392c5db647b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Noteworthy changes in release ?.?? (????-??-??)
 * Bug fixes
   * In interactive mode (-I2), those signals that were blocked at startup
     will remain blocked for the whole period of strace execution.
+  * strace no longer resets SIGCHLD handler in tracees to the default action.
 
 Noteworthy changes in release 4.17 (2017-05-24)
 ===============================================
index 07d5adac903bd2926687a8552bb04ce0d218d845..473572fad9d776ea56b0c4dfc43714e7fdfe41ff 100644 (file)
--- a/strace.c
+++ b/strace.c
@@ -1200,6 +1200,7 @@ struct exec_params {
        gid_t run_egid;
        char **argv;
        char *pathname;
+       struct sigaction child_sa;
 };
 static struct exec_params params_for_tracee;
 
@@ -1254,6 +1255,9 @@ exec_or_die(void)
                alarm(0);
        }
 
+       if (params_for_tracee.child_sa.sa_handler != SIG_DFL)
+               sigaction(SIGCHLD, &params_for_tracee.child_sa, NULL);
+
        execv(params->pathname, params->argv);
        perror_msg_and_die("exec");
 }
@@ -1622,13 +1626,6 @@ init(int argc, char *argv[])
 
        progname = argv[0] ? argv[0] : "strace";
 
-       /* Make sure SIGCHLD has the default action so that waitpid
-          definitely works without losing track of children.  The user
-          should not have given us a bogus state to inherit, but he might
-          have.  Arguably we should detect SIG_IGN here and pass it on
-          to children, but probably noone really needs that.  */
-       signal(SIGCHLD, SIG_DFL);
-
        strace_tracer_pid = getpid();
 
        os_release = get_os_release();
@@ -1821,6 +1818,11 @@ init(int argc, char *argv[])
                tflag = 1;
        }
 
+       sigprocmask(SIG_SETMASK, NULL, &start_set);
+       memcpy(&blocked_set, &start_set, sizeof(blocked_set));
+
+       set_sigaction(SIGCHLD, SIG_DFL, &params_for_tracee.child_sa);
+
 #ifdef USE_LIBUNWIND
        if (stack_trace_enabled) {
                unsigned int tcbi;
@@ -1913,9 +1915,6 @@ init(int argc, char *argv[])
        if (!opt_intr)
                opt_intr = INTR_WHILE_WAIT;
 
-       sigprocmask(SIG_SETMASK, NULL, &start_set);
-       memcpy(&blocked_set, &start_set, sizeof(blocked_set));
-
        /*
         * startup_child() must be called before the signal handlers get
         * installed below as they are inherited into the spawned process.