9
9
#include "khash.h"
10
10
11
11
static const char * const builtin_fsmonitor__daemon_usage [] = {
12
+ N_ ("git fsmonitor--daemon start [<options>]" ),
12
13
N_ ("git fsmonitor--daemon run [<options>]" ),
13
14
N_ ("git fsmonitor--daemon stop" ),
14
15
N_ ("git fsmonitor--daemon status" ),
@@ -22,6 +23,9 @@ static const char * const builtin_fsmonitor__daemon_usage[] = {
22
23
#define FSMONITOR__IPC_THREADS "fsmonitor.ipcthreads"
23
24
static int fsmonitor__ipc_threads = 8 ;
24
25
26
+ #define FSMONITOR__START_TIMEOUT "fsmonitor.starttimeout"
27
+ static int fsmonitor__start_timeout_sec = 60 ;
28
+
25
29
#define FSMONITOR__ANNOUNCE_STARTUP "fsmonitor.announcestartup"
26
30
static int fsmonitor__announce_startup = 0 ;
27
31
@@ -36,6 +40,15 @@ static int fsmonitor_config(const char *var, const char *value, void *cb)
36
40
return 0 ;
37
41
}
38
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
+
39
52
if (!strcmp (var , FSMONITOR__ANNOUNCE_STARTUP )) {
40
53
int is_bool ;
41
54
int i = git_config_bool_or_int (var , value , & is_bool );
@@ -250,7 +263,7 @@ static int fsmonitor_run_daemon(void)
250
263
return err ;
251
264
}
252
265
253
- static int try_to_run_foreground_daemon (void )
266
+ static int try_to_run_foreground_daemon (int detach_console )
254
267
{
255
268
/*
256
269
* Technically, we don't need to probe for an existing daemon
@@ -270,17 +283,106 @@ static int try_to_run_foreground_daemon(void)
270
283
fflush (stderr );
271
284
}
272
285
286
+ #ifdef GIT_WINDOWS_NATIVE
287
+ if (detach_console )
288
+ FreeConsole ();
289
+ #endif
290
+
273
291
return !!fsmonitor_run_daemon ();
274
292
}
275
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
+
276
372
int cmd_fsmonitor__daemon (int argc , const char * * argv , const char * prefix )
277
373
{
278
374
const char * subcmd ;
375
+ int detach_console = 0 ;
279
376
280
377
struct option options [] = {
378
+ OPT_BOOL (0 , "detach" , & detach_console , N_ ("detach from console" )),
281
379
OPT_INTEGER (0 , "ipc-threads" ,
282
380
& fsmonitor__ipc_threads ,
283
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
+
284
386
OPT_END ()
285
387
};
286
388
@@ -296,8 +398,11 @@ int cmd_fsmonitor__daemon(int argc, const char **argv, const char *prefix)
296
398
die (_ ("invalid 'ipc-threads' value (%d)" ),
297
399
fsmonitor__ipc_threads );
298
400
401
+ if (!strcmp (subcmd , "start" ))
402
+ return !!try_to_start_background_daemon ();
403
+
299
404
if (!strcmp (subcmd , "run" ))
300
- return !!try_to_run_foreground_daemon ();
405
+ return !!try_to_run_foreground_daemon (detach_console );
301
406
302
407
if (!strcmp (subcmd , "stop" ))
303
408
return !!do_as_client__send_stop ();
0 commit comments