Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: exec'ing $0 in traps



On Feb 18,  4:39pm, Bart Schaefer wrote:
}
} This affects any process started from a trap -- because the signal
} handler blocks the signal while it executes, all childred spawned or
} exec'd during the trap will have the trap signal blocked.
} 
} Cleaning all this up seems like something entersubsh() should handle;
} proposed patch for that is the first hunk below.

Better formulation of that follows.

} At the same time, install_handler() does not unblock the signal for
} which the trap is being created.
} 
} Second hunk below is what I *believe* should cover this, but I'm not
} very certain.  Other eyeballs?

Further testing shows this is wrong -- removetrap() has been called to
clear the old trap, so sigtrapped[sig] is always 0 at this point.  The
globals from signals.c don't reliably identify which signals are being
blocked or ignored.  However, some testing reveals another difference:

    (sleep 5 && pkill -USR1 sleep) &
    (trap "" USR1; exec zsh -fc "trap : USR1; exec sleep 20")

For bash [4.2.25], an inner USR1 trap like that does not change ignored
state from the parent shell.  Zsh (any version up to the current one)
restores default handling when adding the inner trap, EXCEPT when
using "trap - USR1" in which case the ignored state is preserved.

In short I don't know what to do upon setting a trap, so I'm going to
leave that for now and settle for fixing the (un)block state in the
subshell.

diff --git a/Src/exec.c b/Src/exec.c
index 8f4969f..aea9d0e 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -975,9 +975,8 @@ entersubsh(int flags)
     int sig, monitor, job_control_ok;
 
     if (!(flags & ESUB_KEEPTRAP))
-	for (sig = 0; sig < VSIGCOUNT; sig++)
-	    if (!(sigtrapped[sig] & ZSIG_FUNC) &&
-		sig != SIGDEBUG && sig != SIGZERR)
+	for (sig = 0; sig < SIGCOUNT; sig++)
+	    if (!(sigtrapped[sig] & ZSIG_FUNC))
 		unsettrap(sig);
     monitor = isset(MONITOR);
     job_control_ok = monitor && (flags & ESUB_JOB_CONTROL) && isset(POSIXJOBS);
@@ -1068,6 +1067,18 @@ entersubsh(int flags)
     }
     if (!(sigtrapped[SIGQUIT] & ZSIG_IGNORED))
 	signal_default(SIGQUIT);
+    /*
+     * sigtrapped[sig] == ZSIG_IGNORED for signals that remain ignored,
+     * but other trapped signals are temporarily blocked when intrap,
+     * and must be unblocked before continuing into the subshell.  This
+     * is orthogonal to what the default handler for the signal may be.
+     *
+     * Start loop at 1 because 0 is SIGEXIT
+     */
+    for (sig = 1; sig < SIGCOUNT; sig++)
+	if (intrap && sigtrapped[sig] &&
+	    sigtrapped[sig] != ZSIG_IGNORED)
+	    signal_unblock(signal_mask(sig));
     if (!job_control_ok)
 	opts[MONITOR] = 0;
     opts[USEZLE] = 0;



Messages sorted by: Reverse Date, Date, Thread, Author