Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save x-yuri/50e045babaddc6b1779d8414c825705d to your computer and use it in GitHub Desktop.
Save x-yuri/50e045babaddc6b1779d8414c825705d to your computer and use it in GitHub Desktop.
bash: interrupting commands with async subprocesses when job control is disabled

bash: interrupting commands with async subprocesses when job control is disabled

Subprocesses of async subshells don't inherit SIGINT after trap INT since bash-4.3-rc2:

h. Fixed a bug that caused SIGINT and SIGQUIT to not be trappable in asynchronous subshell commands.

https://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=bash-4.3-rc2&id=b6e23235f28b1c85e18e9a2b7ba8c6b6c46aecbc#n24

Before:

$ bash -c '(trap INT; sleep infinity) & wait'
$ ps -eHo pid,ppid,pgid,tty,stat,ignored,args
    PID    PPID    PGID TT       STAT          IGNORED COMMAND
...
  38886   16721   38886 pts/1    S+   0000000000000004   ./bash -c (trap INT; sleep infinity) & wait
  38887   38886   38886 pts/1    S+   0000000000000004     ./bash -c (trap INT; sleep infinity) & wait
  38888   38887   38886 pts/1    S+   0000000000000006       sleep infinity

sleep has SIGINT set to SIG_IGN. After SIGINT the subshell and sleep remain.

After:

$ bash -c '(trap INT; sleep infinity) & wait'
$ ps -eHo pid,ppid,pgid,tty,stat,ignored,args
    PID    PPID    PGID TT       STAT          IGNORED COMMAND
...
  38893   38818   38893 pts/5    S+   0000000000000004   ./bash -c (trap INT; sleep infinity) & wait
  38894   38893   38893 pts/5    S+   0000000000000004     ./bash -c (trap INT; sleep infinity) & wait
  38895   38894   38893 pts/5    S+   0000000000000000       sleep infinity

sleep has SIGINT set to SIG_DFL. After SIGINT the subshell and sleep exit.

And one can set arbitrary traps in async subshells:

Before:

$ bash -c '(trap "echo \$\$: INT; trap INT; kill -2 \$\$" INT; sleep infinity) & wait'
$ ps -eHo pid,ppid,pgid,tty,stat,ignored,args
    PID    PPID    PGID TT       STAT          IGNORED COMMAND
...
  38900   16721   38900 pts/1    S+   0000000000000004   ./bash -c (trap "echo \$\$: INT; trap INT; kill -2 \$\$"
  38901   38900   38900 pts/1    S+   0000000000000006     ./bash -c (trap "echo \$\$: INT; trap INT; kill -2 \$\
  38902   38901   38900 pts/1    S+   0000000000000006       sleep infinity

The subshell and sleep has SIGINT set to SIG_IGN. After SIGINT they remain.

After:

$ bash -c '(trap "echo \$\$: INT; trap INT; kill -2 \$\$" INT; sleep infinity) & wait'
$ ps -eHo pid,ppid,pgid,tty,stat,ignored,args
    PID    PPID    PGID TT       STAT          IGNORED COMMAND
...
  38907   38818   38907 pts/5    S+   0000000000000004   ./bash -c (trap "echo \$\$: INT; trap INT; kill -2 \$\$"
  38908   38907   38907 pts/5    S+   0000000000000004     ./bash -c (trap "echo \$\$: INT; trap INT; kill -2 \$\
  38909   38908   38907 pts/5    S+   0000000000000000       sleep infinity

The subshell and sleep has SIGINT set to SIG_DFL. After SIGINT they exit. And the trap produces the output.

commit (4.3-rc2)
commit (4.3)
issue

+execute_cmd.c
+	- setup_async_signals: make sure we get the original dispositions for
+	  SIGINT and SIGQUIT before starting the subshell, and don't call
+	  set_signal_ignored  because that sets original_signals[sig].  If we
+	  don't, subsequent attempts to reset handling using trap will fail
+	  because it thinks the original dispositions were SIG_IGN. Posix
+	  interpretation 751 (http://austingroupbugs.net/view.php?id=751)

https://git.savannah.gnu.org/cgit/bash.git/tree/CWRU/changelog?h=bash-4.3-rc2&id=b6e23235f28b1c85e18e9a2b7ba8c6b6c46aecbc#n5554
https://git.savannah.gnu.org/cgit/bash.git/tree/CWRU/changelog?h=bash-4.3&id=ac50fbac377e32b98d2de396f016ea81e8ee9961#n5554

@@ -4794,10 +4809,15 @@ setup_async_signals ()
   if (job_control == 0)
 #endif
     {
+      /* Make sure we get the original signal dispositions now so we don't
+	 confuse the trap builtin later if the subshell tries to use it to
+	 reset SIGINT/SIGQUIT.  Don't call set_signal_ignored; that sets
+	 the value of original_signals to SIG_IGN. Posix interpretation 751. */
+      get_original_signal (SIGINT);
       set_signal_handler (SIGINT, SIG_IGN);
-      set_signal_ignored (SIGINT);
+
+      get_original_signal (SIGQUIT);
       set_signal_handler (SIGQUIT, SIG_IGN);
-      set_signal_ignored (SIGQUIT);
     }
 }

https://git.savannah.gnu.org/cgit/bash.git/tree/execute_cmd.c?h=bash-4.3-rc2&id=b6e23235f28b1c85e18e9a2b7ba8c6b6c46aecbc#n4812
https://git.savannah.gnu.org/cgit/bash.git/tree/execute_cmd.c?h=bash-4.3&id=ac50fbac377e32b98d2de396f016ea81e8ee9961#n4824

the old gist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment