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

Reply via email to