Skip to content

Commit eff10e1

Browse files
derrickstoleedscho
andcommitted
gvfs-helper-client: clean up server process(es)
On Linux, the following command would cause the terminal to be stuck waiting: git fetch origin foobar The issue would be that the fetch would fail with the error fatal: couldn't find remote ref foobar but the underlying git-gvfs-helper process wouldn't die. The `subprocess_exit_handler()` method would close its stdin and stdout, but that wouldn't be enough to cause the process to end, even though the `packet_read_line_gently()` call that is run in `do_sub_cmd__server()` in a loop should return -1 and the process should the terminate peacefully. While it is unclear why this does not happen, there may be other conditions where the `gvfs-helper` process would not terminate. Let's ensure that the gvfs-helper-client process cleans up the gvfs-helper server processes that it spawned upon exit. Reported-by: Stuart Wilcox Humilde <stuartwilcox@microsoft.com> Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 3332e4c commit eff10e1

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

gvfs-helper-client.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,36 @@ static void gh_client__choose_odb(void)
334334
}
335335
}
336336

337+
/*
338+
* Custom exit handler for the `gvfs-helper` subprocesses.
339+
*
340+
* These helper subprocesses will keep waiting for input until they are
341+
* stopped. The default `subprocess_exit_handler()` will instead wait for
342+
* the subprocess to exit, which is not what we want: In case of a fatal
343+
* error, the Git process will exit and the `gvfs-helper` subprocesses will
344+
* need to be stopped explicitly.
345+
*
346+
* The default behavior of `cleanup_children()` does, however, terminate
347+
* the process after calling the `clean_on_exit_handler`. So that's exactly
348+
* what we do here: reproduce the exact same code as
349+
* `subprocess_exit_handler()` modulo waiting for the process that won't
350+
* ever terminate on its own.
351+
*/
352+
static void gh_client__subprocess_exit_handler(struct child_process *process)
353+
{
354+
sigchain_push(SIGPIPE, SIG_IGN);
355+
/* Closing the pipe signals the subprocess to initiate a shutdown. */
356+
close(process->in);
357+
close(process->out);
358+
sigchain_pop(SIGPIPE);
359+
/*
360+
* In contrast to subprocess_exit_handler(), do _not_ wait for the
361+
* process to finish on its own accord: It needs to be terminated via
362+
* a signal, which is what `cleanup_children()` will do after this
363+
* function returns.
364+
*/
365+
}
366+
337367
static struct gh_server__process *gh_client__find_long_running_process(
338368
unsigned int cap_needed)
339369
{
@@ -377,6 +407,9 @@ static struct gh_server__process *gh_client__find_long_running_process(
377407
&entry->subprocess, 1,
378408
&argv, gh_client__start_fn))
379409
FREE_AND_NULL(entry);
410+
else
411+
entry->subprocess.process.clean_on_exit_handler =
412+
gh_client__subprocess_exit_handler;
380413
}
381414

382415
if (entry &&

t/t9210-scalar.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ test_expect_success '`scalar clone` with GVFS-enabled server' '
448448
)
449449
'
450450

451+
test_expect_success 'fetch <non-existent> does not hang in gvfs-helper' '
452+
test_must_fail git -C using-gvfs/src fetch origin does-not-exist
453+
'
454+
451455
test_expect_success '`scalar clone --no-gvfs-protocol` skips gvfs/config' '
452456
# the fake cache server requires fake authentication &&
453457
git config --global core.askPass true &&

0 commit comments

Comments
 (0)