diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c index 468740c197476b..726a3e49118710 100644 --- a/builtin/fsmonitor--daemon.c +++ b/builtin/fsmonitor--daemon.c @@ -67,6 +67,9 @@ static int handle_client(struct ipc_command_listener *data, trace2_data_string("fsmonitor", the_repository, "command", command); if (!strcmp(command, "quit")) { + if (fsmonitor_listen_stop(state)) + error("Could not terminate watcher thread"); + sleep_millisec(50); return SIMPLE_IPC_QUIT; } @@ -165,7 +168,6 @@ int fsmonitor_queue_path(struct fsmonitor_daemon_state *state, static int fsmonitor_run_daemon(int background) { - pthread_t thread; struct fsmonitor_daemon_state state = { { 0 } }; struct ipc_data ipc_data = { .data = { @@ -183,7 +185,7 @@ static int fsmonitor_run_daemon(int background) pthread_mutex_init(&state.initial_mutex, NULL); pthread_mutex_lock(&state.initial_mutex); - if (pthread_create(&thread, NULL, + if (pthread_create(&state.watcher_thread, NULL, (void *(*)(void *)) fsmonitor_listen, &state) < 0) return error(_("could not start fsmonitor listener thread")); diff --git a/compat/fsmonitor/win32.c b/compat/fsmonitor/win32.c index 4639c42254c117..1df28d8e618d55 100644 --- a/compat/fsmonitor/win32.c +++ b/compat/fsmonitor/win32.c @@ -30,6 +30,14 @@ static int process_entry(struct fsmonitor_daemon_state *state, return 0; } +int fsmonitor_listen_stop(struct fsmonitor_daemon_state *state) +{ + if (!TerminateThread(state->watcher_thread.handle, 1)) + return -1; + + return 0; +} + struct fsmonitor_daemon_state *fsmonitor_listen(struct fsmonitor_daemon_state *state) { HANDLE dir; diff --git a/fsmonitor.h b/fsmonitor.h index e2bbb48e95c6c0..7e77cb780a48c9 100644 --- a/fsmonitor.h +++ b/fsmonitor.h @@ -111,6 +111,7 @@ struct fsmonitor_daemon_state { struct fsmonitor_queue_item *first; struct fsmonitor_queue_item *last; uint64_t latest_update; + pthread_t watcher_thread; pthread_mutex_t queue_update_lock, initial_mutex; int error_code; }; @@ -124,6 +125,7 @@ int fsmonitor_queue_path(struct fsmonitor_daemon_state *state, /* This needs to be implemented by the backend */ struct fsmonitor_daemon_state *fsmonitor_listen(struct fsmonitor_daemon_state *state); +int fsmonitor_listen_stop(struct fsmonitor_daemon_state *state); #endif #endif diff --git a/t/t7527-internal-fsmonitor.sh b/t/t7527-internal-fsmonitor.sh index fa2918c8a90992..207c751d6377de 100755 --- a/t/t7527-internal-fsmonitor.sh +++ b/t/t7527-internal-fsmonitor.sh @@ -9,6 +9,13 @@ git fsmonitor--daemon --is-supported || { test_done } +# Tell the fsmonitor--daemon to stop, even if `--stop` failed +test_atexit ' + git fsmonitor--daemon --stop || + test -n "$debug" || + rm -r .git +' + test_expect_success 'can start and stop the daemon' ' test_when_finished \ "test_might_fail git -C test fsmonitor--daemon --stop" &&