Skip to content

Commit 8b74675

Browse files
jeffhostetlerdscho
authored andcommitted
Merge branch 'trial-fsmonitor-march-2022-part3' into trial-fsmonitor-march-2022
2 parents 7e47323 + d607662 commit 8b74675

24 files changed

+2210
-128
lines changed

Makefile

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,14 @@ include shared.mak
477477
#
478478
# If your platform supports a built-in fsmonitor backend, set
479479
# FSMONITOR_DAEMON_BACKEND to the "<name>" of the corresponding
480-
# `compat/fsmonitor/fsm-listen-<name>.c` that implements the
481-
# `fsm_listen__*()` routines.
480+
# `compat/fsmonitor/fsm-listen-<name>.c` and
481+
# `compat/fsmonitor/fsm-health-<name>.c` files
482+
# that implement the `fsm_listen__*()` and `fsm_health__*()` routines.
483+
#
484+
# If your platform has OS-specific ways to tell if a repo is incompatible with
485+
# fsmonitor (whether the hook or IPC daemon version), set FSMONITOR_OS_SETTINGS
486+
# to the "<name>" of the corresponding `compat/fsmonitor/fsm-settings-<name>.c`
487+
# that implements the `fsm_os_settings__*()` routines.
482488
#
483489
# Define DEVELOPER to enable more compiler warnings. Compiler version
484490
# and family are auto detected, but could be overridden by defining
@@ -2012,6 +2018,12 @@ endif
20122018
ifdef FSMONITOR_DAEMON_BACKEND
20132019
COMPAT_CFLAGS += -DHAVE_FSMONITOR_DAEMON_BACKEND
20142020
COMPAT_OBJS += compat/fsmonitor/fsm-listen-$(FSMONITOR_DAEMON_BACKEND).o
2021+
COMPAT_OBJS += compat/fsmonitor/fsm-health-$(FSMONITOR_DAEMON_BACKEND).o
2022+
endif
2023+
2024+
ifdef FSMONITOR_OS_SETTINGS
2025+
COMPAT_CFLAGS += -DHAVE_FSMONITOR_OS_SETTINGS
2026+
COMPAT_OBJS += compat/fsmonitor/fsm-settings-$(FSMONITOR_OS_SETTINGS).o
20152027
endif
20162028

20172029
ifeq ($(TCLTK_PATH),)
@@ -2973,6 +2985,9 @@ GIT-BUILD-OPTIONS: FORCE
29732985
ifdef FSMONITOR_DAEMON_BACKEND
29742986
@echo FSMONITOR_DAEMON_BACKEND=\''$(subst ','\'',$(subst ','\'',$(FSMONITOR_DAEMON_BACKEND)))'\' >>$@+
29752987
endif
2988+
ifdef FSMONITOR_OS_SETTINGS
2989+
@echo FSMONITOR_OS_SETTINGS=\''$(subst ','\'',$(subst ','\'',$(FSMONITOR_OS_SETTINGS)))'\' >>$@+
2990+
endif
29762991
ifdef TEST_OUTPUT_DIRECTORY
29772992
@echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst ','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@+
29782993
endif

builtin/fsmonitor--daemon.c

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "parse-options.h"
44
#include "fsmonitor.h"
55
#include "fsmonitor-ipc.h"
6+
#include "compat/fsmonitor/fsm-health.h"
67
#include "compat/fsmonitor/fsm-listen.h"
78
#include "fsmonitor--daemon.h"
89
#include "simple-ipc.h"
@@ -1136,6 +1137,18 @@ void fsmonitor_publish(struct fsmonitor_daemon_state *state,
11361137
pthread_mutex_unlock(&state->main_lock);
11371138
}
11381139

1140+
static void *fsm_health__thread_proc(void *_state)
1141+
{
1142+
struct fsmonitor_daemon_state *state = _state;
1143+
1144+
trace2_thread_start("fsm-health");
1145+
1146+
fsm_health__loop(state);
1147+
1148+
trace2_thread_exit();
1149+
return NULL;
1150+
}
1151+
11391152
static void *fsm_listen__thread_proc(void *_state)
11401153
{
11411154
struct fsmonitor_daemon_state *state = _state;
@@ -1174,18 +1187,21 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
11741187
*/
11751188
.uds_disallow_chdir = 0
11761189
};
1190+
int health_started = 0;
1191+
int listener_started = 0;
1192+
int err = 0;
11771193

11781194
/*
11791195
* Start the IPC thread pool before the we've started the file
11801196
* system event listener thread so that we have the IPC handle
11811197
* before we need it.
11821198
*/
11831199
if (ipc_server_run_async(&state->ipc_server_data,
1184-
fsmonitor_ipc__get_path(), &ipc_opts,
1200+
state->path_ipc.buf, &ipc_opts,
11851201
handle_client, state))
11861202
return error_errno(
11871203
_("could not start IPC thread pool on '%s'"),
1188-
fsmonitor_ipc__get_path());
1204+
state->path_ipc.buf);
11891205

11901206
/*
11911207
* Start the fsmonitor listener thread to collect filesystem
@@ -1194,15 +1210,31 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
11941210
if (pthread_create(&state->listener_thread, NULL,
11951211
fsm_listen__thread_proc, state) < 0) {
11961212
ipc_server_stop_async(state->ipc_server_data);
1197-
ipc_server_await(state->ipc_server_data);
1213+
err = error(_("could not start fsmonitor listener thread"));
1214+
goto cleanup;
1215+
}
1216+
listener_started = 1;
11981217

1199-
return error(_("could not start fsmonitor listener thread"));
1218+
/*
1219+
* Start the health thread to watch over our process.
1220+
*/
1221+
if (pthread_create(&state->health_thread, NULL,
1222+
fsm_health__thread_proc, state) < 0) {
1223+
ipc_server_stop_async(state->ipc_server_data);
1224+
err = error(_("could not start fsmonitor health thread"));
1225+
goto cleanup;
12001226
}
1227+
health_started = 1;
12011228

12021229
/*
12031230
* The daemon is now fully functional in background threads.
1231+
* Our primary thread should now just wait while the threads
1232+
* do all the work.
1233+
*/
1234+
cleanup:
1235+
/*
12041236
* Wait for the IPC thread pool to shutdown (whether by client
1205-
* request or from filesystem activity).
1237+
* request, from filesystem activity, or an error).
12061238
*/
12071239
ipc_server_await(state->ipc_server_data);
12081240

@@ -1211,23 +1243,38 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
12111243
* event from the IPC thread pool, but it doesn't hurt to tell
12121244
* it again. And wait for it to shutdown.
12131245
*/
1214-
fsm_listen__stop_async(state);
1215-
pthread_join(state->listener_thread, NULL);
1246+
if (listener_started) {
1247+
fsm_listen__stop_async(state);
1248+
pthread_join(state->listener_thread, NULL);
1249+
}
1250+
1251+
if (health_started) {
1252+
fsm_health__stop_async(state);
1253+
pthread_join(state->health_thread, NULL);
1254+
}
12161255

1217-
return state->error_code;
1256+
if (err)
1257+
return err;
1258+
if (state->listen_error_code)
1259+
return state->listen_error_code;
1260+
if (state->health_error_code)
1261+
return state->health_error_code;
1262+
return 0;
12181263
}
12191264

12201265
static int fsmonitor_run_daemon(void)
12211266
{
12221267
struct fsmonitor_daemon_state state;
1268+
const char *home;
12231269
int err;
12241270

12251271
memset(&state, 0, sizeof(state));
12261272

12271273
hashmap_init(&state.cookies, cookies_cmp, NULL, 0);
12281274
pthread_mutex_init(&state.main_lock, NULL);
12291275
pthread_cond_init(&state.cookies_cond, NULL);
1230-
state.error_code = 0;
1276+
state.listen_error_code = 0;
1277+
state.health_error_code = 0;
12311278
state.current_token_data = fsmonitor_new_token_data();
12321279

12331280
/* Prepare to (recursively) watch the <worktree-root> directory. */
@@ -1289,6 +1336,15 @@ static int fsmonitor_run_daemon(void)
12891336

12901337
strbuf_addch(&state.path_cookie_prefix, '/');
12911338

1339+
/*
1340+
* We create a named-pipe or unix domain socket inside of the
1341+
* ".git" directory. (Well, on Windows, we base our named
1342+
* pipe in the NPFS on the absolute path of the git
1343+
* directory.)
1344+
*/
1345+
strbuf_init(&state.path_ipc, 0);
1346+
strbuf_addstr(&state.path_ipc, absolute_path(fsmonitor_ipc__get_path()));
1347+
12921348
/*
12931349
* Confirm that we can create platform-specific resources for the
12941350
* filesystem listener before we bother starting all the threads.
@@ -1298,18 +1354,42 @@ static int fsmonitor_run_daemon(void)
12981354
goto done;
12991355
}
13001356

1357+
if (fsm_health__ctor(&state)) {
1358+
err = error(_("could not initialize health thread"));
1359+
goto done;
1360+
}
1361+
1362+
/*
1363+
* CD out of the worktree root directory.
1364+
*
1365+
* The common Git startup mechanism causes our CWD to be the
1366+
* root of the worktree. On Windows, this causes our process
1367+
* to hold a locked handle on the CWD. This prevents the
1368+
* worktree from being moved or deleted while the daemon is
1369+
* running.
1370+
*
1371+
* We assume that our FS and IPC listener threads have either
1372+
* opened all of the handles that they need or will do
1373+
* everything using absolute paths.
1374+
*/
1375+
home = getenv("HOME");
1376+
if (home && *home && chdir(home))
1377+
die_errno(_("could not cd home '%s'"), home);
1378+
13011379
err = fsmonitor_run_daemon_1(&state);
13021380

13031381
done:
13041382
pthread_cond_destroy(&state.cookies_cond);
13051383
pthread_mutex_destroy(&state.main_lock);
13061384
fsm_listen__dtor(&state);
1385+
fsm_health__dtor(&state);
13071386

13081387
ipc_server_free(state.ipc_server_data);
13091388

13101389
strbuf_release(&state.path_worktree_watch);
13111390
strbuf_release(&state.path_gitdir_watch);
13121391
strbuf_release(&state.path_cookie_prefix);
1392+
strbuf_release(&state.path_ipc);
13131393

13141394
return err;
13151395
}
@@ -1449,6 +1529,12 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
14491529
die(_("invalid 'ipc-threads' value (%d)"),
14501530
fsmonitor__ipc_threads);
14511531

1532+
prepare_repo_settings(the_repository);
1533+
fsm_settings__set_ipc(the_repository);
1534+
1535+
if (fsm_settings__error_if_incompatible(the_repository))
1536+
return 1;
1537+
14521538
if (!strcmp(subcmd, "start"))
14531539
return !!try_to_start_background_daemon();
14541540

builtin/update-index.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,10 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
12571257

12581258
if (fsmonitor > 0) {
12591259
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
1260+
1261+
if (fsm_settings__error_if_incompatible(the_repository))
1262+
return 1;
1263+
12601264
if (fsm_mode == FSMONITOR_MODE_DISABLED) {
12611265
warning(_("core.fsmonitor is unset; "
12621266
"set it if you really want to "

compat/fsmonitor/fsm-health-darwin.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "cache.h"
2+
#include "config.h"
3+
#include "fsmonitor.h"
4+
#include "fsm-health.h"
5+
#include "fsmonitor--daemon.h"
6+
7+
int fsm_health__ctor(struct fsmonitor_daemon_state *state)
8+
{
9+
return 0;
10+
}
11+
12+
void fsm_health__dtor(struct fsmonitor_daemon_state *state)
13+
{
14+
return;
15+
}
16+
17+
void fsm_health__loop(struct fsmonitor_daemon_state *state)
18+
{
19+
return;
20+
}
21+
22+
void fsm_health__stop_async(struct fsmonitor_daemon_state *state)
23+
{
24+
}

0 commit comments

Comments
 (0)