Skip to content

Commit 344fd32

Browse files
committed
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 bd63763 commit 344fd32

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

git.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "builtin.h"
44
#include "gvfs.h"
5+
#include "gvfs-helper-client.h"
56
#include "config.h"
67
#include "environment.h"
78
#include "exec-cmd.h"
@@ -982,6 +983,7 @@ int cmd_main(int argc, const char **argv)
982983

983984
trace_command_performance(argv);
984985
atexit(post_command_hook_atexit);
986+
atexit(stop_gh_server_subprocesses);
985987

986988
/*
987989
* "git-xxxx" is the same as "git xxxx", but we obviously:

gvfs-helper-client.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,42 @@ static struct object_directory *gh_client__chosen_odb;
3838
#define CAP_OBJECTS__VERB_POST_NAME "post"
3939
#define CAP_OBJECTS__VERB_PREFETCH_NAME "prefetch"
4040

41+
void stop_gh_server_subprocesses(void)
42+
{
43+
struct gh_server__process *entry, **entries;
44+
struct hashmap_iter iter;
45+
size_t i = 0, size;
46+
47+
if (!gh_server__subprocess_map_initialized)
48+
return;
49+
50+
/*
51+
* Since `subprocess_stop()` modifies the hashmap by removing the
52+
* respective subprocess, we cannot use `hashmap_for_each_entry()`
53+
* directly, but have to copy the entries to an array first.
54+
*/
55+
size = hashmap_get_size(&gh_server__subprocess_map);
56+
ALLOC_ARRAY(entries, size);
57+
hashmap_for_each_entry(&gh_server__subprocess_map,
58+
&iter, entry, subprocess)
59+
entries[i++] = entry;
60+
if (i != size)
61+
BUG("gh_server__subprocess_map: size mismatch: "
62+
"%"PRIuMAX" != %"PRIuMAX,
63+
(uintmax_t)i, (uintmax_t)size);
64+
while(i--) {
65+
subprocess_stop(&gh_server__subprocess_map,
66+
&entries[i]->subprocess);
67+
FREE_AND_NULL(entries[i]);
68+
}
69+
70+
FREE_AND_NULL(entries);
71+
72+
hashmap_clear_and_free(&gh_server__subprocess_map,
73+
struct gh_server__process, subprocess);
74+
gh_server__subprocess_map_initialized = 0;
75+
}
76+
4177
static int gh_client__start_fn(struct subprocess_entry *subprocess)
4278
{
4379
static int versions[] = {1, 0};

gvfs-helper-client.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,9 @@ int gh_client__drain_queue(enum gh_client__created *p_ghc);
8484
int gh_client__prefetch(timestamp_t seconds_since_epoch,
8585
int *nr_packfiles_received);
8686

87+
/*
88+
* Clean up long-running processes at and of the Git process.
89+
*/
90+
void stop_gh_server_subprocesses(void);
91+
8792
#endif /* GVFS_HELPER_CLIENT_H */

0 commit comments

Comments
 (0)