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 <pclouds@xxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html