Skip to content

Commit b8d292f

Browse files
derrickstoleedscho
authored 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> Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 1030eb5 commit b8d292f

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

gvfs-helper-client.c

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

338+
static void stop_gh_server_subprocesses(void)
339+
{
340+
struct gh_server__process *entry, **entries;
341+
struct hashmap_iter iter;
342+
size_t i = 0, size;
343+
344+
if (!gh_server__subprocess_map_initialized)
345+
return;
346+
347+
/*
348+
* Since `subprocess_stop()` modifies the hashmap by removing the
349+
* respective subprocess, we cannot use `hashmap_for_each_entry()`
350+
* directly, but have to copy the entries to an array first.
351+
*/
352+
size = hashmap_get_size(&gh_server__subprocess_map);
353+
ALLOC_ARRAY(entries, size);
354+
hashmap_for_each_entry(&gh_server__subprocess_map,
355+
&iter, entry, subprocess)
356+
entries[i++] = entry;
357+
if (i != size)
358+
BUG("gh_server__subprocess_map: size mismatch: "
359+
"%"PRIuMAX" != %"PRIuMAX,
360+
i, size);
361+
while(i--)
362+
subprocess_stop(&gh_server__subprocess_map,
363+
&entries[i]->subprocess);
364+
FREE_AND_NULL(entries);
365+
366+
hashmap_clear(&gh_server__subprocess_map);
367+
gh_server__subprocess_map_initialized = 0;
368+
}
369+
338370
static struct gh_server__process *gh_client__find_long_running_process(
339371
unsigned int cap_needed)
340372
{
@@ -373,6 +405,7 @@ static struct gh_server__process *gh_client__find_long_running_process(
373405
gh_server__subprocess_map_initialized = 1;
374406
hashmap_init(&gh_server__subprocess_map,
375407
(hashmap_cmp_fn)cmd2process_cmp, NULL, 0);
408+
atexit(stop_gh_server_subprocesses);
376409
entry = NULL;
377410
} else
378411
entry = (struct gh_server__process *)subprocess_find_entry(

0 commit comments

Comments
 (0)