diff options
Diffstat (limited to 'Functions/Misc/zargs')
-rw-r--r-- | Functions/Misc/zargs | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/Functions/Misc/zargs b/Functions/Misc/zargs index ecd69f7e4..782d6811e 100644 --- a/Functions/Misc/zargs +++ b/Functions/Misc/zargs @@ -39,18 +39,21 @@ # # "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. # -# With the --max-procs option, zargs may not correctly capture the exit -# status of the backgrounded jobs, because of limitations of the "wait" -# builtin. If the zsh/parameter module is not available, the status is -# NEVER correctly returned, otherwise the status of the longest-running -# job in each batch is captured. +# 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. # -# Also because of "wait" limitations, --max-procs spawns max-procs jobs, -# then waits for all of those, then spawns another batch, etc. +# Because of "wait" limitations, --max-procs spawns max-procs jobs, then +# waits for all of those, then spawns another batch, etc. +# +# The maximum number of parallel jobs for which exit status is available +# is determined by the sysconf CHILD_MAX parameter, which can't be read +# or changed from within the shell. # # Differences from POSIX xargs: # @@ -69,6 +72,13 @@ # -I/-L and implementations reportedly differ.) In zargs, -i/-I have # this behavior, as do -l/-L, but when -i/-I appear anywhere then -l/-L # are ignored (forced to 1). +# +# * 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 @@ -83,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.5" - if zparseopts -a opts -D -- \ -eof::=eof e::=eof \ -exit x \ @@ -192,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=' @@ -262,19 +281,19 @@ fi if (( P != 1 && ARGC > 1 )) then - # These setopts are necessary for "wait" on multiple jobs to work. - setopt nonotify nomonitor - bg='&' - if zmodload -i zsh/parameter 2>/dev/null - then - wait='wait ${${jobstates[(R)running:*]/#*:/}/%=*/}' - else - wait='wait' - fi + setopt nonotify # Do not report each exiting job + local -a _zajobs + local j + bg='& _zajobs+=( $! )' + analyze=' + for j in $_zajobs; do + wait $j + '"$analyze"' + done; _zajobs=()' fi -# Everything has to be in a subshell just in case of backgrounding jobs, -# so that we don't unintentionally "wait" for jobs of the parent shell. +# Everything has to be in a subshell so that we don't "wait" for any +# unrelated jobs of the parent shell. ( while ((ARGC)) @@ -313,4 +332,8 @@ return $ret ) +} always { + builtin unfunction _zarun _zatraps +} + # } |