|
9 | 9 | #include "parse-options.h" |
10 | 10 | #include "thread-utils.h" |
11 | 11 | #include "strvec.h" |
| 12 | +#include "run-command.h" |
12 | 13 |
|
13 | 14 | #ifndef SUPPORTS_SIMPLE_IPC |
14 | 15 | int cmd__simple_ipc(int argc, const char **argv) |
@@ -267,185 +268,71 @@ static int daemon__run_server(void) |
267 | 268 | */ |
268 | 269 | ret = ipc_server_run(cl_args.path, &opts, test_app_cb, (void*)&my_app_data); |
269 | 270 | if (ret == -2) |
270 | | - error(_("socket/pipe already in use: '%s'"), cl_args.path); |
| 271 | + error("socket/pipe already in use: '%s'", cl_args.path); |
271 | 272 | else if (ret == -1) |
272 | | - error_errno(_("could not start server on: '%s'"), cl_args.path); |
| 273 | + error_errno("could not start server on: '%s'", cl_args.path); |
273 | 274 |
|
274 | 275 | return ret; |
275 | 276 | } |
276 | 277 |
|
277 | | -#ifndef GIT_WINDOWS_NATIVE |
278 | | -/* |
279 | | - * This is adapted from `daemonize()`. Use `fork()` to directly create and |
280 | | - * run the daemon in a child process. |
281 | | - */ |
282 | | -static int spawn_server(pid_t *pid) |
283 | | -{ |
284 | | - struct ipc_server_opts opts = { |
285 | | - .nr_threads = cl_args.nr_threads, |
286 | | - }; |
| 278 | +static start_bg_wait_cb bg_wait_cb; |
287 | 279 |
|
288 | | - *pid = fork(); |
289 | | - |
290 | | - switch (*pid) { |
291 | | - case 0: |
292 | | - if (setsid() == -1) |
293 | | - error_errno(_("setsid failed")); |
294 | | - close(0); |
295 | | - close(1); |
296 | | - close(2); |
297 | | - sanitize_stdfds(); |
| 280 | +static int bg_wait_cb(const struct child_process *cp, void *cb_data) |
| 281 | +{ |
| 282 | + int s = ipc_get_active_state(cl_args.path); |
298 | 283 |
|
299 | | - return ipc_server_run(cl_args.path, &opts, test_app_cb, |
300 | | - (void*)&my_app_data); |
| 284 | + switch (s) { |
| 285 | + case IPC_STATE__LISTENING: |
| 286 | + /* child is "ready" */ |
| 287 | + return 0; |
301 | 288 |
|
302 | | - case -1: |
303 | | - return error_errno(_("could not spawn daemon in the background")); |
| 289 | + case IPC_STATE__NOT_LISTENING: |
| 290 | + case IPC_STATE__PATH_NOT_FOUND: |
| 291 | + /* give child more time */ |
| 292 | + return 1; |
304 | 293 |
|
305 | 294 | default: |
306 | | - return 0; |
| 295 | + case IPC_STATE__INVALID_PATH: |
| 296 | + case IPC_STATE__OTHER_ERROR: |
| 297 | + /* all the time in world won't help */ |
| 298 | + return -1; |
307 | 299 | } |
308 | 300 | } |
309 | | -#else |
310 | | -/* |
311 | | - * Conceptually like `daemonize()` but different because Windows does not |
312 | | - * have `fork(2)`. Spawn a normal Windows child process but without the |
313 | | - * limitations of `start_command()` and `finish_command()`. |
314 | | - */ |
315 | | -static int spawn_server(pid_t *pid) |
316 | | -{ |
317 | | - char test_tool_exe[MAX_PATH]; |
318 | | - struct strvec args = STRVEC_INIT; |
319 | | - int in, out; |
320 | | - |
321 | | - GetModuleFileNameA(NULL, test_tool_exe, MAX_PATH); |
322 | | - |
323 | | - in = open("/dev/null", O_RDONLY); |
324 | | - out = open("/dev/null", O_WRONLY); |
325 | | - |
326 | | - strvec_push(&args, test_tool_exe); |
327 | | - strvec_push(&args, "simple-ipc"); |
328 | | - strvec_push(&args, "run-daemon"); |
329 | | - strvec_pushf(&args, "--name=%s", cl_args.path); |
330 | | - strvec_pushf(&args, "--threads=%d", cl_args.nr_threads); |
331 | | - |
332 | | - *pid = mingw_spawnvpe(args.v[0], args.v, NULL, NULL, in, out, out); |
333 | | - close(in); |
334 | | - close(out); |
335 | | - |
336 | | - strvec_clear(&args); |
337 | 301 |
|
338 | | - if (*pid < 0) |
339 | | - return error(_("could not spawn daemon in the background")); |
340 | | - |
341 | | - return 0; |
342 | | -} |
343 | | -#endif |
344 | | - |
345 | | -/* |
346 | | - * This is adapted from `wait_or_whine()`. Watch the child process and |
347 | | - * let it get started and begin listening for requests on the socket |
348 | | - * before reporting our success. |
349 | | - */ |
350 | | -static int wait_for_server_startup(pid_t pid_child) |
| 302 | +static int daemon__start_server(void) |
351 | 303 | { |
352 | | - int status; |
353 | | - pid_t pid_seen; |
354 | | - enum ipc_active_state s; |
355 | | - time_t time_limit, now; |
| 304 | + struct child_process cp = CHILD_PROCESS_INIT; |
| 305 | + enum start_bg_result sbgr; |
356 | 306 |
|
357 | | - time(&time_limit); |
358 | | - time_limit += cl_args.max_wait_sec; |
| 307 | + strvec_push(&cp.args, "test-tool"); |
| 308 | + strvec_push(&cp.args, "simple-ipc"); |
| 309 | + strvec_push(&cp.args, "run-daemon"); |
| 310 | + strvec_pushf(&cp.args, "--name=%s", cl_args.path); |
| 311 | + strvec_pushf(&cp.args, "--threads=%d", cl_args.nr_threads); |
359 | 312 |
|
360 | | - for (;;) { |
361 | | - pid_seen = waitpid(pid_child, &status, WNOHANG); |
| 313 | + cp.no_stdin = 1; |
| 314 | + cp.no_stdout = 1; |
| 315 | + cp.no_stderr = 1; |
362 | 316 |
|
363 | | - if (pid_seen == -1) |
364 | | - return error_errno(_("waitpid failed")); |
| 317 | + sbgr = start_bg_command(&cp, bg_wait_cb, NULL, cl_args.max_wait_sec); |
365 | 318 |
|
366 | | - else if (pid_seen == 0) { |
367 | | - /* |
368 | | - * The child is still running (this should be |
369 | | - * the normal case). Try to connect to it on |
370 | | - * the socket and see if it is ready for |
371 | | - * business. |
372 | | - * |
373 | | - * If there is another daemon already running, |
374 | | - * our child will fail to start (possibly |
375 | | - * after a timeout on the lock), but we don't |
376 | | - * care (who responds) if the socket is live. |
377 | | - */ |
378 | | - s = ipc_get_active_state(cl_args.path); |
379 | | - if (s == IPC_STATE__LISTENING) |
380 | | - return 0; |
381 | | - |
382 | | - time(&now); |
383 | | - if (now > time_limit) |
384 | | - return error(_("daemon not online yet")); |
385 | | - |
386 | | - continue; |
387 | | - } |
| 319 | + switch (sbgr) { |
| 320 | + case SBGR_READY: |
| 321 | + return 0; |
388 | 322 |
|
389 | | - else if (pid_seen == pid_child) { |
390 | | - /* |
391 | | - * The new child daemon process shutdown while |
392 | | - * it was starting up, so it is not listening |
393 | | - * on the socket. |
394 | | - * |
395 | | - * Try to ping the socket in the odd chance |
396 | | - * that another daemon started (or was already |
397 | | - * running) while our child was starting. |
398 | | - * |
399 | | - * Again, we don't care who services the socket. |
400 | | - */ |
401 | | - s = ipc_get_active_state(cl_args.path); |
402 | | - if (s == IPC_STATE__LISTENING) |
403 | | - return 0; |
| 323 | + default: |
| 324 | + case SBGR_ERROR: |
| 325 | + case SBGR_CB_ERROR: |
| 326 | + return error("daemon failed to start"); |
404 | 327 |
|
405 | | - /* |
406 | | - * We don't care about the WEXITSTATUS() nor |
407 | | - * any of the WIF*(status) values because |
408 | | - * `cmd__simple_ipc()` does the `!!result` |
409 | | - * trick on all function return values. |
410 | | - * |
411 | | - * So it is sufficient to just report the |
412 | | - * early shutdown as an error. |
413 | | - */ |
414 | | - return error(_("daemon failed to start")); |
415 | | - } |
| 328 | + case SBGR_TIMEOUT: |
| 329 | + return error("daemon not online yet"); |
416 | 330 |
|
417 | | - else |
418 | | - return error(_("waitpid is confused")); |
| 331 | + case SBGR_DIED: |
| 332 | + return error("daemon terminated"); |
419 | 333 | } |
420 | 334 | } |
421 | 335 |
|
422 | | -/* |
423 | | - * This process will start a simple-ipc server in a background process and |
424 | | - * wait for it to become ready. This is like `daemonize()` but gives us |
425 | | - * more control and better error reporting (and makes it easier to write |
426 | | - * unit tests). |
427 | | - */ |
428 | | -static int daemon__start_server(void) |
429 | | -{ |
430 | | - pid_t pid_child; |
431 | | - int ret; |
432 | | - |
433 | | - /* |
434 | | - * Run the actual daemon in a background process. |
435 | | - */ |
436 | | - ret = spawn_server(&pid_child); |
437 | | - if (pid_child <= 0) |
438 | | - return ret; |
439 | | - |
440 | | - /* |
441 | | - * Let the parent wait for the child process to get started |
442 | | - * and begin listening for requests on the socket. |
443 | | - */ |
444 | | - ret = wait_for_server_startup(pid_child); |
445 | | - |
446 | | - return ret; |
447 | | -} |
448 | | - |
449 | 336 | /* |
450 | 337 | * This process will run a quick probe to see if a simple-ipc server |
451 | 338 | * is active on this path. |
@@ -548,7 +435,7 @@ static int client__stop_server(void) |
548 | 435 |
|
549 | 436 | time(&now); |
550 | 437 | if (now > time_limit) |
551 | | - return error(_("daemon has not shutdown yet")); |
| 438 | + return error("daemon has not shutdown yet"); |
552 | 439 | } |
553 | 440 | } |
554 | 441 |
|
|
0 commit comments