commit: 1dcc4326956b8e6a2912ff4133d25a11f683b30b
Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
AuthorDate: Fri Jan 30 06:38:04 2026 +0000
Commit: Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Fri Feb 6 01:45:14 2026 +0000
URL:
https://gitweb.gentoo.org/proj/gentoo-functions.git/commit/?id=1dcc4326
Respect exit status of initial subshell in parallel_run()
Presently, the parallel_run() function spawns a subshell before
proceeding to execute any background commands, thereby ensuring that the
subsequent invocation of the wait builtin reaps only the subprocesses
that were created as a direct consequence of calling the function.
However, consider a scenario in which the aforementioned subshell is
prematurely terminated. Naturally, it begins by calling parallel_run.
$ bash -c '. /lib/gentoo/functions.sh; parallel_run 2 sleep-fail 30 30'
The behaviour of the "sleep-fail" executable is to sleep for the given
number of seconds before unconditionally exiting 1. With the two jobs in
flight, the process hierarchy will be as follows.
bash(2)───bash(3)─┬─bash(4)───sleep-fail(6)
└─bash(5)───sleep-fail(7)
Note that the original shell has a PID of 2, and the initial subshell a
PID of 3, with two further subshells serving as worker processes. Now,
imagine that PID 3 dies in isolation (for whatever reason).
$ kill 3 # issued before 30 seconds has elapsed
With the compound command having concluded, the original shell will
proceed to execute the last command of the function.
! rmdir -- "${statedir}" 2>/dev/null
The presence of the state directory is relied upon to determine whether
at least one job has failed. However, since both instances of sleep-fail
have yet to exit, this command will yield 0. The caller is thus deluded
into believing that all of the jobs have successfully completed.
Address this issue by returning the exit status of the compound command,
provided that it is non-zero. Otherwise, return the inverted exit status
of rmdir(1), as before.
As regards the aformentioned scenario, killing the initial subshell
shall now cause the function to return 143 (SIGTERM), rather than 0.
Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
Signed-off-by: Sam James <sam <AT> gentoo.org>
functions.sh | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/functions.sh b/functions.sh
index 0e57224..9172788 100644
--- a/functions.sh
+++ b/functions.sh
@@ -416,7 +416,7 @@ oldest()
#
parallel_run()
{
- local arg cmd i statedir w workers
+ local arg cmd i retval statedir w workers
if [ "$#" -lt 3 ]; then
warn "parallel_run: too few arguments (got $#, expected at
least 3)"
@@ -446,7 +446,11 @@ parallel_run()
done
wait
)
- ! rmdir -- "${statedir}" 2>/dev/null
+ retval=$?
+ if rmdir -- "${statedir}" 2>/dev/null && [ "${retval}" -eq 0 ]; then
+ retval=1
+ fi
+ return "${retval}"
}
#