1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00

Fix race condition in coprocess test with external 'cat'

The race is between '$cat |&' and 'kill $pid'. In between, there
are only a variable assignment and two buffered writes, so there
is nothing that waits for the external 'cat' to finish forking,
execve'ing and initialising -- meaning there is no guarantee it is
ready to catch SIGTERM. This explains the hang; 'cat' misses the
signal, continues to initialise, and simply waits for more input.

src/cmd/ksh93/tests/coprocess.sh:
- Actually read from the /bin/cat coprocess and verify that it
  works. This has the beneficial side effect of ensuring it is
  fully loaded and initialised before SIGTERMing it.

Resolves: https://github.com/ksh93/ksh/issues/132
This commit is contained in:
Martijn Dekker 2022-07-10 06:16:52 +02:00
parent 1934686de3
commit 893ea066f7

View file

@ -215,15 +215,17 @@ do
trap - TERM trap - TERM
[[ $sleep_pid ]] && kill $sleep_pid [[ $sleep_pid ]] && kill $sleep_pid
# TODO: The /bin/cat iteration of this test is known to hang intermittently on Debian and trap 'sleep_pid=; kill $pid; err_exit "$cat coprocess 2 hung"' TERM
# derived systems (such as Ubuntu). See: https://github.com/ksh93/ksh/issues/132
trap 'sleep_pid=; kill $pid; warning "$cat coprocess 2 hung (known issue, help us fix it at <https://github.com/ksh93/ksh/issues/132>)"' TERM
{ sleep 5; kill $$; } & { sleep 5; kill $$; } &
sleep_pid=$! sleep_pid=$!
$cat |& $cat |&
pid=$! pid=$!
print foo >&p 2> /dev/null || err_exit "first write of foo to $cat coprocess failed" print foo1 >&p 2> /dev/null || err_exit "first write to $cat coprocess failed"
print foo >&p 2> /dev/null || err_exit "second write of foo to coprocess failed" print foo2 >&p 2> /dev/null || err_exit "second write to $cat coprocess failed"
# avoid race between '$cat |&' initialising and 'kill $pid': read from the coprocess
# before 'kill' so that $cat is known to be fully initialised and ready to catch SIGTERM
read <&p && [[ $REPLY == foo1 ]] || err_exit "first read from $cat coprocess failed"
read <&p && [[ $REPLY == foo2 ]] || err_exit "second read from $cat coprocess failed"
kill $pid kill $pid
wait $pid 2> /dev/null wait $pid 2> /dev/null
trap - TERM trap - TERM