Skip to content

Commit 3963e68

Browse files
jeffhostetlergitster
authored andcommitted
fsmonitor--daemon: cd out of worktree root
Teach the fsmonitor--daemon to CD outside of the worktree before starting up. The common Git startup mechanism causes the CWD of the daemon process to be in the root of the worktree. On Windows, this causes the daemon process to hold a locked handle on the CWD and prevents other processes from moving or deleting the worktree while the daemon is running. CD to HOME before entering main event loops. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent ed1b7c3 commit 3963e68

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

builtin/fsmonitor--daemon.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,11 +1181,11 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
11811181
* before we need it.
11821182
*/
11831183
if (ipc_server_run_async(&state->ipc_server_data,
1184-
fsmonitor_ipc__get_path(), &ipc_opts,
1184+
state->path_ipc.buf, &ipc_opts,
11851185
handle_client, state))
11861186
return error_errno(
11871187
_("could not start IPC thread pool on '%s'"),
1188-
fsmonitor_ipc__get_path());
1188+
state->path_ipc.buf);
11891189

11901190
/*
11911191
* Start the fsmonitor listener thread to collect filesystem
@@ -1220,6 +1220,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
12201220
static int fsmonitor_run_daemon(void)
12211221
{
12221222
struct fsmonitor_daemon_state state;
1223+
const char *home;
12231224
int err;
12241225

12251226
memset(&state, 0, sizeof(state));
@@ -1289,6 +1290,15 @@ static int fsmonitor_run_daemon(void)
12891290

12901291
strbuf_addch(&state.path_cookie_prefix, '/');
12911292

1293+
/*
1294+
* We create a named-pipe or unix domain socket inside of the
1295+
* ".git" directory. (Well, on Windows, we base our named
1296+
* pipe in the NPFS on the absolute path of the git
1297+
* directory.)
1298+
*/
1299+
strbuf_init(&state.path_ipc, 0);
1300+
strbuf_addstr(&state.path_ipc, absolute_path(fsmonitor_ipc__get_path()));
1301+
12921302
/*
12931303
* Confirm that we can create platform-specific resources for the
12941304
* filesystem listener before we bother starting all the threads.
@@ -1298,6 +1308,23 @@ static int fsmonitor_run_daemon(void)
12981308
goto done;
12991309
}
13001310

1311+
/*
1312+
* CD out of the worktree root directory.
1313+
*
1314+
* The common Git startup mechanism causes our CWD to be the
1315+
* root of the worktree. On Windows, this causes our process
1316+
* to hold a locked handle on the CWD. This prevents the
1317+
* worktree from being moved or deleted while the daemon is
1318+
* running.
1319+
*
1320+
* We assume that our FS and IPC listener threads have either
1321+
* opened all of the handles that they need or will do
1322+
* everything using absolute paths.
1323+
*/
1324+
home = getenv("HOME");
1325+
if (home && *home && chdir(home))
1326+
die_errno(_("could not cd home '%s'"), home);
1327+
13011328
err = fsmonitor_run_daemon_1(&state);
13021329

13031330
done:
@@ -1310,6 +1337,7 @@ static int fsmonitor_run_daemon(void)
13101337
strbuf_release(&state.path_worktree_watch);
13111338
strbuf_release(&state.path_gitdir_watch);
13121339
strbuf_release(&state.path_cookie_prefix);
1340+
strbuf_release(&state.path_ipc);
13131341

13141342
return err;
13151343
}

compat/fsmonitor/fsm-listen-win32.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -402,12 +402,22 @@ static int recv_rdcw_watch(struct one_watch *watch)
402402
}
403403

404404
/*
405-
* NEEDSWORK: If an external <gitdir> is deleted, the above
406-
* returns an error. I'm not sure that there's anything that
407-
* we can do here other than failing -- the <worktree>/.git
408-
* link file would be broken anyway. We might try to check
409-
* for that and return a better error message, but I'm not
410-
* sure it is worth it.
405+
* GetOverlappedResult() fails if the watched directory is
406+
* deleted while we were waiting for an overlapped IO to
407+
* complete. The documentation did not list specific errors,
408+
* but I observed ERROR_ACCESS_DENIED (0x05) errors during
409+
* testing.
410+
*
411+
* Note that we only get notificaiton events for events
412+
* *within* the directory, not *on* the directory itself.
413+
* (These might be properies of the parent directory, for
414+
* example).
415+
*
416+
* NEEDSWORK: We might try to check for the deleted directory
417+
* case and return a better error message, but I'm not sure it
418+
* is worth it.
419+
*
420+
* Shutdown if we get any error.
411421
*/
412422

413423
error(_("GetOverlappedResult failed on '%s' [GLE %ld]"),

fsmonitor--daemon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ struct fsmonitor_daemon_state {
5454
struct fsmonitor_daemon_backend_data *backend_data;
5555

5656
struct ipc_server_data *ipc_server_data;
57+
struct strbuf path_ipc;
5758
};
5859

5960
/*

0 commit comments

Comments
 (0)