about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2022-06-08 20:41:24 -0700
committerBart Schaefer <schaefer@zsh.org>2022-06-08 20:41:24 -0700
commit52761c94185f8405d8069c1d4bacc8b5210a1850 (patch)
tree53d3d5e0fdfd7844a11874f24b9f2e878ac46773
parentb26b6b3fe00b94a2d4370b1afd2644034947b6b8 (diff)
downloadzsh-52761c94185f8405d8069c1d4bacc8b5210a1850.tar.gz
zsh-52761c94185f8405d8069c1d4bacc8b5210a1850.tar.xz
zsh-52761c94185f8405d8069c1d4bacc8b5210a1850.zip
50335: simplify "wait" usage, fix signal handling
- remove the preliminary "wait" for all the process
- remove "nomonitor" (because it was only needed for that "wait")
- explicitly adds traps to exit for tty-generated signals plus TERM
- capture the signal trap context and restore it in background jobs
- wrap in an "always" block to clean up local helper functions
- update comments to note another buglet and drop support for zsh 4.x.
-rw-r--r--ChangeLog5
-rw-r--r--Functions/Misc/zargs40
2 files changed, 35 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 71f879776..c13d8a163 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2022-06-08  Bart Schaefer  <schaefer@zsh.org>
+
+	* 50335: Functions/Misc/zargs: simplify "wait" usage, fix signal
+	handling for functions used as the command.
+
 2022-06-07  Peter Stephenson  <p.stephenson@samsung.com>
 
 	* 50339: Doc/Zsh/options.yo, Src/text.c, Test/C04funcdef.ztst:
diff --git a/Functions/Misc/zargs b/Functions/Misc/zargs
index 81916a3ac..782d6811e 100644
--- a/Functions/Misc/zargs
+++ b/Functions/Misc/zargs
@@ -39,9 +39,14 @@
 #
 # "Killed by a signal" is determined by the usual shell rule that $? is
 # the signal number plus 128, so zargs can be fooled by a command that
-# explicitly exits with 129+.  Also, zsh prior to 4.1.x returns 1 rather
-# than 127 for "command not found" so this function incorrectly returns
-# 123 in that case if used with zsh 4.0.x.
+# explicitly exits with 129+.  If the command passed to zargs is a shell
+# function which uses "exit" instead of "return", zsh interprets 129+ as
+# a signal sent to the process group and may terminate zargs with that
+# status.  This is avoided when running zargs -P 2 or greater.
+#
+# ZARGS_VERSION 1.5 is the last to support zsh 4.x.  Also, zsh prior to
+# 4.1.x returns 1 rather than 127 for "command not found" so zargs
+# incorrectly returned 123 in that case if used with zsh 4.0.x.
 #
 # Because of "wait" limitations, --max-procs spawns max-procs jobs, then
 # waits for all of those, then spawns another batch, etc.
@@ -71,6 +76,10 @@
 # * The use of SIGUSR1 and SIGUSR2 to change the number of parallel jobs
 #   is not supported.
 
+{ # Begin "always" block to reset locally defined functions
+
+local ZARGS_VERSION="1.8"
+
 # First, capture the current setopts as "sticky emulation"
 if zmodload zsh/parameter
 then
@@ -84,11 +93,20 @@ else
   emulate $(emulate -l) -c '_zarun() { eval "$@" }'
 fi
 
+local _zaTRAPS="$(trap)"
+_zatraps() {
+  # In children, these traps may be reset to default behavior, even
+  # if the calling shell has traps.  Restore to surrounding context,
+  # but assure that if zargs itself is signaled, children will exit.
+  [[ -o interactive ]] &&
+    function TRAP{HUP,INT,QUIT,TERM} { exit $((128 + $1)) }
+  [[ -n "$_zaTRAPS" ]] && eval "$_zaTRAPS"
+  unset _zaTRAPS
+}
+
 emulate -L zsh || return 1
 local -a opts eof n s l P i
 
-local ZARGS_VERSION="1.7"
-
 if zparseopts -a opts -D -- \
 	-eof::=eof e::=eof \
 	-exit x \
@@ -193,14 +211,14 @@ then (( c = $#command - 1 ))
 else command=( print -r -- )
 fi
 
-local wait bg
-local execute='
+local bg execute='
     if (( $opts[(I)-(-interactive|p)] ))
     then read -q "?$call?..." || continue
     elif (( $opts[(I)-(-verbose|t)] ))
     then print -u2 -r -- "$call"
     fi
     _zarun "{
+	_zatraps
 	\"\${call[@]}\"
     } $bg"'
 local ret=0 analyze='
@@ -263,12 +281,10 @@ fi
 
 if (( P != 1 && ARGC > 1 ))
 then
-    # These setopts are necessary for "wait" on multiple jobs to work.
-    setopt nonotify nomonitor
+    setopt nonotify	# Do not report each exiting job
     local -a _zajobs
     local j
     bg='& _zajobs+=( $! )'
-    wait='wait'
     analyze='
     for j in $_zajobs; do
       wait $j
@@ -316,4 +332,8 @@ return $ret
 
 )
 
+} always {
+  builtin unfunction _zarun _zatraps
+}
+
 # }