9
#include "khash.h"
10
11
static const char * const builtin_fsmonitor__daemon_usage[] = {
12
+ N_("git fsmonitor--daemon start [<options>]"),
13
N_("git fsmonitor--daemon run [<options>]"),
14
N_("git fsmonitor--daemon stop"),
15
N_("git fsmonitor--daemon status"),
23
#define FSMONITOR__IPC_THREADS "fsmonitor.ipcthreads"
24
static int fsmonitor__ipc_threads = 8;
25
26
+#define FSMONITOR__START_TIMEOUT "fsmonitor.starttimeout"
27
+static int fsmonitor__start_timeout_sec = 60;
28
+
29
#define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup"
30
static int fsmonitor__announce_startup = 0;
31
40
return 0;
41
}
42
43
+ if (!strcmp(var, FSMONITOR__START_TIMEOUT)) {
44
+ int i = git_config_int(var, value);
45
+ if (i < 0)
46
+ return error(_("value of '%s' out of range: %d"),
47
+ FSMONITOR__START_TIMEOUT, i);
48
+ fsmonitor__start_timeout_sec = i;
49
+ return 0;
50
+ }
51
+
52
if (!strcmp(var, FSMONITOR__ANNOUNCE_STARTUP)) {
53
int is_bool;
54
int i = git_config_bool_or_int(var, value, &is_bool);
263
return err;
264
}
265
253
-static int try_to_run_foreground_daemon(void)
266
+static int try_to_run_foreground_daemon(int detach_console)
267
{
268
/*
269
* Technically, we don't need to probe for an existing daemon
283
fflush(stderr);
284
}
285
286
+#ifdef GIT_WINDOWS_NATIVE
287
+ if (detach_console)
288
+ FreeConsole();
289
+#endif
290
+
291
return !!fsmonitor_run_daemon();
292
}
293
294
+static start_bg_wait_cb bg_wait_cb;
295
+
296
+static int bg_wait_cb(const struct child_process *cp, void *cb_data)
297
+{
298
+ enum ipc_active_state s = fsmonitor_ipc__get_state();
299
+
300
+ switch (s) {
301
+ case IPC_STATE__LISTENING:
302
+ /* child is "ready" */
303
+ return 0;
304
+
305
+ case IPC_STATE__NOT_LISTENING:
306
+ case IPC_STATE__PATH_NOT_FOUND:
307
+ /* give child more time */
308
+ return 1;
309
+
310
+ default:
311
+ case IPC_STATE__INVALID_PATH:
312
+ case IPC_STATE__OTHER_ERROR:
313
+ /* all the time in world won't help */
314
+ return -1;
315
+ }
316
+}
317
+
318
+static int try_to_start_background_daemon(void)
319
+{
320
+ struct child_process cp = CHILD_PROCESS_INIT;
321
+ enum start_bg_result sbgr;
322
+
323
+ /*
324
+ * Before we try to create a background daemon process, see
325
+ * if a daemon process is already listening. This makes it
326
+ * easier for us to report an already-listening error to the
327
+ * console, since our spawn/daemon can only report the success
328
+ * of creating the background process (and not whether it
329
+ * immediately exited).
330
+ */
331
+ if (fsmonitor_ipc__get_state() == IPC_STATE__LISTENING)
332
+ die(_("fsmonitor--daemon is already running '%s'"),
333
+ the_repository->worktree);
334
+
335
+ if (fsmonitor__announce_startup) {
336
+ fprintf(stderr, _("starting fsmonitor-daemon in '%s'\n"),
337
+ the_repository->worktree);
338
+ fflush(stderr);
339
+ }
340
+
341
+ cp.git_cmd = 1;
342
+
343
+ strvec_push(&cp.args, "fsmonitor--daemon");
344
+ strvec_push(&cp.args, "run");
345
+ strvec_push(&cp.args, "--detach");
346
+ strvec_pushf(&cp.args, "--ipc-threads=%d", fsmonitor__ipc_threads);
347
+
348
+ cp.no_stdin = 1;
349
+ cp.no_stdout = 1;
350
+ cp.no_stderr = 1;
351
+
352
+ sbgr = start_bg_command(&cp, bg_wait_cb, NULL,
353
+ fsmonitor__start_timeout_sec);
354
+
355
+ switch (sbgr) {
356
+ case SBGR_READY:
357
+ return 0;
358
+
359
+ default:
360
+ case SBGR_ERROR:
361
+ case SBGR_CB_ERROR:
362
+ return error(_("daemon failed to start"));
363
+
364
+ case SBGR_TIMEOUT:
365
+ return error(_("daemon not online yet"));
366
+
367
+ case SBGR_DIED:
368
+ return error(_("daemon terminated"));
369
+ }
370
+}
371
+
372
int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
373
{
374
const char *subcmd;
375
+ int detach_console = 0;
376
377
struct option options[] = {
378
+ OPT_BOOL(0, "detach", &detach_console, N_("detach from console")),
379
OPT_INTEGER(0, "ipc-threads",
380
&fsmonitor__ipc_threads,
381
N_("use <n> ipc worker threads")),
382
+ OPT_INTEGER(0, "start-timeout",
383
+ &fsmonitor__start_timeout_sec,
384
+ N_("max seconds to wait for background daemon startup")),
385
+
386
OPT_END()
387
};
388
398
die(_("invalid 'ipc-threads' value (%d)"),
399
fsmonitor__ipc_threads);
400
401
+ if (!strcmp(subcmd, "start"))
402
+ return !!try_to_start_background_daemon();
403
+
404
if (!strcmp(subcmd, "run"))
300
- return !!try_to_run_foreground_daemon();
405
+ return !!try_to_run_foreground_daemon(detach_console);
406
407
if (!strcmp(subcmd, "stop"))
408
return !!do_as_client__send_stop();