If $GIT_DIR/index.watcher or $GIT_DIR/index is gone, exit. We could
watch this path too, but we'll waste precious resources (at least with
inotify). And with inotify, it seems to miss the case when $GIT_DIR is
moved. Just check if the socket path still exists every minute.

As the last resort, if we do not receive any commands in the last 6
hours, exit. The code is structured this way because later on inotify
is also polled. On an busy watched directory, the timeout may never
happen for us to kil the watcher, even if index.watcher is already
gone.

For mass cleanup, "killall -USR1 git-file-watcher" asks every watcher
process to question the purpose of its existence.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 file-watcher.c | 38 +++++++++++++++++++++++++++++++++++---
 1 file changed, 35 insertions(+), 3 deletions(-)

diff --git a/file-watcher.c b/file-watcher.c
index df06529..f334e23 100644
--- a/file-watcher.c
+++ b/file-watcher.c
@@ -163,6 +163,12 @@ static void daemonize(void)
 #endif
 }
 
+static int check_exit_please;
+static void check_exit_signal(int signo)
+{
+       check_exit_please = 1;
+}
+
 int main(int argc, const char **argv)
 {
        struct strbuf sb = STRBUF_INIT;
@@ -172,6 +178,8 @@ int main(int argc, const char **argv)
        const char *prefix;
        int daemon = 0, quiet = 0, shutdown = 0;
        const char *log_string = NULL;
+       struct stat socket_st;
+       struct timeval tv_last_command;
        struct option options[] = {
                OPT__QUIET(&quiet, N_("be quiet")),
                OPT_BOOL(0, "daemon", &daemon,
@@ -217,6 +225,10 @@ int main(int argc, const char **argv)
 
        atexit(cleanup);
        sigchain_push_common(cleanup_on_signal);
+       sigchain_push(SIGUSR1, check_exit_signal);
+
+       if (stat(socket_path, &socket_st))
+               die_errno("failed to stat %s", socket_path);
 
        if (daemon) {
                strbuf_addf(&sb, "%s.log", socket_path);
@@ -234,17 +246,37 @@ int main(int argc, const char **argv)
        pfd[nr].fd = fd;
        pfd[nr++].events = POLLIN;
 
+       gettimeofday(&tv_last_command, NULL);
        for (;;) {
-               if (poll(pfd, nr, -1) < 0) {
+               int check_exit = check_exit_please;
+               int ret = poll(pfd, nr, check_exit ? 0 : 60 * 1000);
+               if (ret < 0) {
                        if (errno != EINTR) {
                                error("Poll failed, resuming: %s", 
strerror(errno));
                                sleep(1);
                        }
                        continue;
+               } else if (!ret)
+                       check_exit = 1;
+
+               if ((pfd[0].revents & POLLIN)) {
+                       if (handle_command(fd))
+                               break;
+                       gettimeofday(&tv_last_command, NULL);
                }
 
-               if ((pfd[0].revents & POLLIN) && handle_command(fd))
-                       break;
+               if (check_exit) {
+                       struct stat st;
+                       struct timeval now;
+                       gettimeofday(&now, NULL);
+                       if (tv_last_command.tv_sec + 6 * 60 < now.tv_sec)
+                               break;
+                       if (stat(socket_path, &st) ||
+                           st.st_ino != socket_st.st_ino ||
+                           stat(get_index_file(), &st))
+                               break;
+                       check_exit_please = 0;
+               }
        }
        return 0;
 }
-- 
1.8.5.1.208.g05b12ea

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to