Message ID | 20250106-b4-pks-ci-fixes-v2-2-06ae540771b7@pks.im (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | A couple of CI improvements | expand |
On Mon, Jan 06, 2025 at 12:16:51PM +0100, Patrick Steinhardt wrote: > Fix the issue by making the writer fill the pipe buffer before we > execute git-submodule(1). Ideally, it would be git-submodule(1) itself > that does produce all that data, but it would require us to create a > large amount of submodules, which is inefficient. Instead, we use Perl > to print gibberish until the buffer is filled. > > To verify that this works as expected one can apply the following patch > to the preimage of this commit, which used to reliably trigger the race: > > diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh > index f21e920367..9338c75626 100755 > --- a/t/t7422-submodule-output.sh > +++ b/t/t7422-submodule-output.sh > @@ -168,7 +168,7 @@ done > > test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' ' > { git submodule status --recursive 2>err; echo $?>status; } | > - grep -q X/S && > + { sleep 1 && grep -q X/S; } && > test_must_be_empty err && > test_match_signal 13 "$(cat status)" > ' > > With the pipe-stuffing workaround the test runs successfully. Sadly this isn't enough. The pipe-stuffing solves the race with grep _starting_ (and thus the extra "sleep"), but the fundamental race we've seen in practice still remains. See my reply the v1 thread for details. -Peff
diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh index f21e9203678b94701281d5339ae8bfe53d5de0ed..976f91b0ebd9d82daee3802a212dd3f4031fe86b 100755 --- a/t/t7422-submodule-output.sh +++ b/t/t7422-submodule-output.sh @@ -167,8 +167,14 @@ do done test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' ' - { git submodule status --recursive 2>err; echo $?>status; } | - grep -q X/S && + { + # Stuff pipe buffer full of input so that `git submodule + # status` will block on write; this script will write over + # 128kb. + perl -le "print q{foo} for (1..33000)" && + git submodule status --recursive 2>err + echo $?>status + } | grep -q X/S && test_must_be_empty err && test_match_signal 13 "$(cat status)" '
One test in t7422 asserts that `git submodule status --recursive` properly handles SIGPIPE. This test is flaky though and may sometimes not see a SIGPIPE at all: expecting success of 7422.18 'git submodule status --recursive propagates SIGPIPE': { git submodule status --recursive 2>err; echo $?>status; } | grep -q X/S && test_must_be_empty err && test_match_signal 13 "$(cat status)" ++ git submodule status --recursive ++ grep -q X/S ++ echo 0 ++ test_must_be_empty err ++ test 1 -ne 1 ++ test_path_is_file err ++ test 1 -ne 1 ++ test -f err ++ test -s err +++ cat status ++ test_match_signal 13 0 ++ test 0 = 141 ++ test 0 = 269 ++ return 1 error: last command exited with $?=1 not ok 18 - git submodule status --recursive propagates SIGPIPE The issue is caused by us using grep(1) to terminate the pipe on the first matching line in the recursing git-submodule(1) process. Standard streams are typically buffered though, so this condition is racy and may cause us to terminate the pipe after git-submodule(1) has already exited, and in that case we wouldn't see the expected signal. Fix the issue by making the writer fill the pipe buffer before we execute git-submodule(1). Ideally, it would be git-submodule(1) itself that does produce all that data, but it would require us to create a large amount of submodules, which is inefficient. Instead, we use Perl to print gibberish until the buffer is filled. To verify that this works as expected one can apply the following patch to the preimage of this commit, which used to reliably trigger the race: diff --git a/t/t7422-submodule-output.sh b/t/t7422-submodule-output.sh index f21e920367..9338c75626 100755 --- a/t/t7422-submodule-output.sh +++ b/t/t7422-submodule-output.sh @@ -168,7 +168,7 @@ done test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' ' { git submodule status --recursive 2>err; echo $?>status; } | - grep -q X/S && + { sleep 1 && grep -q X/S; } && test_must_be_empty err && test_match_signal 13 "$(cat status)" ' With the pipe-stuffing workaround the test runs successfully. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Patrick Steinhardt <ps@pks.im> --- t/t7422-submodule-output.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)