On 3/5/26 12:40, Chet Ramey wrote:
It depends. Do you have a specific reproducer that works outside of
reboot?
Thanks for hinting this could be done without reboot.
Here it is.
# foo.sh ######################
#! /usr/bin/env bash
set -ex
function errtrap() {
trap - EXIT TERM
echo "errtrap"
i=0
while (( ++i <= 100 )); do
echo "cleanup $i"
sleep 1
done
return 0
}
function termtrap() {
trap - EXIT TERM
echo "termtrap"
return 0
}
trap 'errtrap || true' EXIT
trap 'termtrap || true; kill -TERM $$' TERM
sleep infinity
##############################
Started with:
strace -o foo.strace -- bash foo.sh >trace 2>&1 </dev/null
Got the PIDs for the script and the underlying sleep commands.
Then killed both using:
env kill -s SIGTERM --verbose --timeout 0 SIGHUP $PID_SLEEP $PID_SCRIPT
Excerpt from strace output:
access("/usr/bin/sleep", R_OK) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_BLOCK, [INT TERM CHLD], [], 8) = 0
clone(child_stack=NULL,
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0x7f0c15601a10) = 102976
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x55db9bc00fe0, sa_mask=[],
sa_flags=SA_RESTORER, sa_restorer=0x7f0c1523fc30},
{sa_handler=0x55db9bc2aaa0, sa_mask=[HUP INT ILL TRAP ABRT BUS FPE USR1
SEGV USR2 PIPE ALRM TE
RM XCPU XFSZ VTALRM SYS], sa_flags=SA_RESTORER,
sa_restorer=0x7f0c1523fc30}, 8) = 0
wait4(-1, 0x7ffca17a8e40, 0, NULL) = ? ERESTARTSYS (To be
restarted if SA_RESTART is set)
--- SIGHUP {si_signo=SIGHUP, si_code=SI_QUEUE, si_pid=103126,
si_uid=1000, si_int=15, si_ptr=0xf} ---
rt_sigreturn({mask=[CHLD]}) = -1 EINTR (Interrupted system
call)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_QUEUE, si_pid=103126,
si_uid=1000, si_int=15, si_ptr=0xf} ---
rt_sigreturn({mask=[CHLD]}) = -1 EINTR (Interrupted system
call)
rt_sigprocmask(SIG_BLOCK, [CHLD], [CHLD], 8) = 0
rt_sigprocmask(SIG_SETMASK, [CHLD], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [CHLD], 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [CHLD], 8) = 0
rt_sigprocmask(SIG_SETMASK, [CHLD], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [CHLD], 8) = 0
write(2, "+++ termtrap\n", 13) = 13
write(2, "+++ trap - EXIT TERM\n", 21) = 21
rt_sigaction(SIGTERM, {sa_handler=0x55db9bc2aaa0, sa_mask=[],
sa_flags=SA_RESTORER, sa_restorer=0x7f0c1523fc30},
{sa_handler=0x55db9bc25ad0, sa_mask=[], sa_flags=SA_RESTORER,
sa_restorer=0x7f0c1523fc30}, 8) = 0
write(2, "+++ echo termtrap\n", 18) = 18
fstat(1, {st_mode=S_IFREG|0640, st_size=145, ...}) = 0
write(1, "termtrap\n", 9) = 9
write(2, "+++ return 0\n", 13) = 13
write(2, "+++ kill -TERM 102975\n", 22) = 22
kill(102975, SIGTERM) = 0
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=102975,
si_uid=1000} ---
rt_sigreturn({mask=[CHLD]}) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [CHLD], 8) = 0
rt_sigprocmask(SIG_SETMASK, [CHLD], NULL, 8) = 0
write(2, "++ errtrap\n", 11) = 11
write(2, "++ trap - EXIT TERM\n", 20) = 20
write(2, "++ echo errtrap\n", 16) = 16
write(1, "errtrap\n", 8) = 8
write(2, "++ i=0\n", 7) = 7
write(2, "++ (( ++i <= 100 ))\n", 22) = 22
rt_sigprocmask(SIG_BLOCK, [CHLD], [CHLD], 8) = 0
rt_sigprocmask(SIG_SETMASK, [CHLD], NULL, 8) = 0
write(2, "++ echo 'cleanup 1'\n", 20) = 20
write(1, "cleanup 1\n", 10) = 10
write(2, "++ sleep 1\n", 11) = 11
So the kill(self, TERM) is sent and received, after the TERM (and EXIT)
trap is disabled, but that does not prevent the EXIT trap to execute in
its entirety.
--
Daniel