* Starts seamless worker process doing the actual work (config loading, ...) * * @param configs Files to read config from * @param closeConsoleLog Whether to close the console log after config loading * @param stderrFile Where to log errors * * @return The worker's PID on success, -1 on fork(2) failure, -2 if the worker couldn't load its config */
| 462 | * @return The worker's PID on success, -1 on fork(2) failure, -2 if the worker couldn't load its config |
| 463 | */ |
| 464 | static pid_t StartUnixWorker(const std::vector<std::string>& configs, bool closeConsoleLog = false, const String& stderrFile = String()) |
| 465 | { |
| 466 | Log(LogNotice, "cli") |
| 467 | << "Spawning seamless worker process doing the actual work"; |
| 468 | |
| 469 | try { |
| 470 | Application::UninitializeBase(); |
| 471 | } catch (const std::exception& ex) { |
| 472 | Log(LogCritical, "cli") |
| 473 | << "Failed to stop thread pool before forking, unexpected error: " << DiagnosticInformation(ex); |
| 474 | exit(EXIT_FAILURE); |
| 475 | } |
| 476 | |
| 477 | /* Block the signal handlers we'd like to change in the child process until we changed them. |
| 478 | * Block SIGUSR2 handler until we've set l_CurrentlyStartingUnixWorkerPid. |
| 479 | */ |
| 480 | (void)sigprocmask(SIG_BLOCK, &l_UnixWorkerSignals, nullptr); |
| 481 | |
| 482 | pid_t pid = fork(); |
| 483 | |
| 484 | switch (pid) { |
| 485 | case -1: |
| 486 | Log(LogCritical, "cli") |
| 487 | << "fork() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\""; |
| 488 | |
| 489 | try { |
| 490 | Application::InitializeBase(); |
| 491 | } catch (const std::exception& ex) { |
| 492 | Log(LogCritical, "cli") |
| 493 | << "Failed to re-initialize thread pool after forking (parent): " << DiagnosticInformation(ex); |
| 494 | exit(EXIT_FAILURE); |
| 495 | } |
| 496 | |
| 497 | (void)sigprocmask(SIG_UNBLOCK, &l_UnixWorkerSignals, nullptr); |
| 498 | return -1; |
| 499 | |
| 500 | case 0: |
| 501 | try { |
| 502 | { |
| 503 | struct sigaction sa; |
| 504 | memset(&sa, 0, sizeof(sa)); |
| 505 | |
| 506 | sa.sa_handler = SIG_DFL; |
| 507 | |
| 508 | (void)sigaction(SIGUSR1, &sa, nullptr); |
| 509 | } |
| 510 | |
| 511 | { |
| 512 | struct sigaction sa; |
| 513 | memset(&sa, 0, sizeof(sa)); |
| 514 | |
| 515 | sa.sa_handler = SIG_IGN; |
| 516 | |
| 517 | (void)sigaction(SIGHUP, &sa, nullptr); |
| 518 | } |
| 519 | |
| 520 | { |
| 521 | struct sigaction sa; |