submodule status: propagate SIGPIPE

It has been reported than running git submodule status --recurse | grep -q ^+ results in an unexpected error message fatal: failed to recurse into submodule $submodule When "git submodule--helper" recurses into a submodule it creates a child process. If that process fails then the error message above is displayed by the parent. In the case above the child is killed by SIGPIPE as "grep -q" exits as soon as it sees the first match. Fix this by propagating SIGPIPE so that it is visible to the process running git. We could propagate other signals but I'm not sure there is much value in doing that. In the common case of the user pressing Ctrl-C or Ctrl-\ then SIGINT or SIGQUIT will be sent to the foreground process group and so the parent process will receive the same signal as the child. Reported-by: Matt Liberty <mliberty@precisioninno.com> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Phillip Wood committed Sep 20, 2024 at 13:07 UTC 082caf527ea769635e8c46d0cc181c844c50defd
2 files changed +12 -1
builtin/submodule--helper.c
+5 -1
@@ -694,6 +694,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
694
695 if (flags & OPT_RECURSIVE) {
696 struct child_process cpr = CHILD_PROCESS_INIT;
697 + int res;
698
699 cpr.git_cmd = 1;
700 cpr.dir = path;
@@ -709,7 +710,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
710 if (flags & OPT_QUIET)
711 strvec_push(&cpr.args, "--quiet");
712
712 - if (run_command(&cpr))
713 + res = run_command(&cpr);
714 + if (res == SIGPIPE + 128)
715 + raise(SIGPIPE);
716 + else if (res)
717 die(_("failed to recurse into submodule '%s'"), path);
718 }
719
t/t7422-submodule-output.sh
+7
@@ -167,4 +167,11 @@ do
167 '
168 done
169
170 +test_expect_success !MINGW 'git submodule status --recursive propagates SIGPIPE' '
171 + { git submodule status --recursive 2>err; echo $?>status; } |
172 + grep -q X/S &&
173 + test_must_be_empty err &&
174 + test_match_signal 13 "$(cat status)"
175 +'
176 +
177 test_done