+static void watcher_cb_stdin(uv_poll_t *handle, int status, int events) {
+ char c;
+ int r;
+
+ if ((errno = -status)) diee("watcher: poll stdin");
+ for (;;) {
+ r= read(0, &c, 1);
+ if (r!=-1) _exit(0);
+ if (!(errno==EINTR || errno==EWOULDBLOCK || errno==EAGAIN))
+ diee("watcher: read sentinel stdin");
+ }
+}
+
+static void watcher_cb_sockpath(uv_fs_event_t *handle, const char *filename,
+ int events, int status) {
+ int r;
+ struct stat now_stab;
+
+ if ((errno = -status)) diee("watcher: poll stdin");
+ for (;;) {
+ r= stat(socket_path, &now_stab);
+ if (r==-1) {
+ if (errno==ENOENT) _exit(0);
+ if (errno==EINTR) continue;
+ diee("stat socket: %s", socket_path);
+ }
+ if (!(now_stab.st_dev == initial_stab.st_dev &&
+ now_stab.st_ino == initial_stab.st_ino))
+ _exit(0);
+ }
+}
+
+// On entry, stderr is still inherited, but 0 and 1 are the pipes
+static __attribute__((noreturn))
+void become_watcher(void) {
+ uv_loop_t loop;
+ uv_poll_t uvhandle_stdin;
+ uv_fs_event_t uvhandle_sockpath;
+ int r;
+
+ if (fcntl(0, F_SETFL, O_NONBLOCK)) diee("watcher set stdin nonblocking");
+
+ errno= -uv_loop_init(&loop);
+ if (errno) diee("watcher: uv_loop_init");
+
+ errno= -uv_poll_init(&loop, &uvhandle_stdin, 0);
+ if (errno) diee("watcher: uv_poll_init");
+ errno= -uv_poll_start(&uvhandle_stdin,
+ UV_READABLE | UV_WRITABLE | UV_DISCONNECT,
+ watcher_cb_stdin);
+ if (errno) diee("watcher: uv_poll_start");
+
+ errno= -uv_fs_event_init(&loop, &uvhandle_sockpath);
+ if (errno) diee("watcher: uv_fs_event_init");
+
+ errno= -uv_fs_event_start(&uvhandle_sockpath, watcher_cb_sockpath,
+ socket_path, 0);
+ if (errno) diee("watcher: uv_fs_event_start");
+
+ // OK everything is set up, let us daemonise
+ if (dup2(1,2) != 2) diee("watcher: set daemonised stderr");
+ r= setvbuf(stderr, 0, _IOLBF, BUFSIZ);
+ if (r) diee("watcher: setvbuf stderr");
+
+ pid_t child = fork();
+ if (child == (pid_t)-1) diee("watcher: fork");
+ if (child) _exit(0);
+
+ if (setsid() == (pid_t)-1) diee("watcher: setsid");
+
+ r= uv_run(&loop, UV_RUN_DEFAULT);
+ die("uv_run returned (%d)", r);
+}
+