aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--builtin/fsmonitor--daemon.c32
-rw-r--r--compat/fsmonitor/fsm-listen-win32.c22
-rw-r--r--fsmonitor--daemon.h1
3 files changed, 47 insertions, 8 deletions
diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 66b78a0353..db297649da 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -1181,11 +1181,11 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
* before we need it.
*/
if (ipc_server_run_async(&state->ipc_server_data,
- fsmonitor_ipc__get_path(), &ipc_opts,
+ state->path_ipc.buf, &ipc_opts,
handle_client, state))
return error_errno(
_("could not start IPC thread pool on '%s'"),
- fsmonitor_ipc__get_path());
+ state->path_ipc.buf);
/*
* Start the fsmonitor listener thread to collect filesystem
@@ -1220,6 +1220,7 @@ static int fsmonitor_run_daemon_1(struct fsmonitor_daemon_state *state)
static int fsmonitor_run_daemon(void)
{
struct fsmonitor_daemon_state state;
+ const char *home;
int err;
memset(&state, 0, sizeof(state));
@@ -1290,6 +1291,15 @@ static int fsmonitor_run_daemon(void)
strbuf_addch(&state.path_cookie_prefix, '/');
/*
+ * We create a named-pipe or unix domain socket inside of the
+ * ".git" directory. (Well, on Windows, we base our named
+ * pipe in the NPFS on the absolute path of the git
+ * directory.)
+ */
+ strbuf_init(&state.path_ipc, 0);
+ strbuf_addstr(&state.path_ipc, absolute_path(fsmonitor_ipc__get_path()));
+
+ /*
* Confirm that we can create platform-specific resources for the
* filesystem listener before we bother starting all the threads.
*/
@@ -1298,6 +1308,23 @@ static int fsmonitor_run_daemon(void)
goto done;
}
+ /*
+ * CD out of the worktree root directory.
+ *
+ * The common Git startup mechanism causes our CWD to be the
+ * root of the worktree. On Windows, this causes our process
+ * to hold a locked handle on the CWD. This prevents the
+ * worktree from being moved or deleted while the daemon is
+ * running.
+ *
+ * We assume that our FS and IPC listener threads have either
+ * opened all of the handles that they need or will do
+ * everything using absolute paths.
+ */
+ home = getenv("HOME");
+ if (home && *home && chdir(home))
+ die_errno(_("could not cd home '%s'"), home);
+
err = fsmonitor_run_daemon_1(&state);
done:
@@ -1310,6 +1337,7 @@ done:
strbuf_release(&state.path_worktree_watch);
strbuf_release(&state.path_gitdir_watch);
strbuf_release(&state.path_cookie_prefix);
+ strbuf_release(&state.path_ipc);
return err;
}
diff --git a/compat/fsmonitor/fsm-listen-win32.c b/compat/fsmonitor/fsm-listen-win32.c
index 4f46bd1d0a..35f2fb9578 100644
--- a/compat/fsmonitor/fsm-listen-win32.c
+++ b/compat/fsmonitor/fsm-listen-win32.c
@@ -424,12 +424,22 @@ static int recv_rdcw_watch(struct one_watch *watch)
}
/*
- * NEEDSWORK: If an external <gitdir> is deleted, the above
- * returns an error. I'm not sure that there's anything that
- * we can do here other than failing -- the <worktree>/.git
- * link file would be broken anyway. We might try to check
- * for that and return a better error message, but I'm not
- * sure it is worth it.
+ * GetOverlappedResult() fails if the watched directory is
+ * deleted while we were waiting for an overlapped IO to
+ * complete. The documentation did not list specific errors,
+ * but I observed ERROR_ACCESS_DENIED (0x05) errors during
+ * testing.
+ *
+ * Note that we only get notificaiton events for events
+ * *within* the directory, not *on* the directory itself.
+ * (These might be properies of the parent directory, for
+ * example).
+ *
+ * NEEDSWORK: We might try to check for the deleted directory
+ * case and return a better error message, but I'm not sure it
+ * is worth it.
+ *
+ * Shutdown if we get any error.
*/
error(_("GetOverlappedResult failed on '%s' [GLE %ld]"),
diff --git a/fsmonitor--daemon.h b/fsmonitor--daemon.h
index bd09fffc17..223c2131b5 100644
--- a/fsmonitor--daemon.h
+++ b/fsmonitor--daemon.h
@@ -54,6 +54,7 @@ struct fsmonitor_daemon_state {
struct fsmonitor_daemon_backend_data *backend_data;
struct ipc_server_data *ipc_server_data;
+ struct strbuf path_ipc;
};
/*