| 56 | }; |
| 57 | |
| 58 | int main() |
| 59 | { |
| 60 | try |
| 61 | { |
| 62 | boost::asio::io_context io_context; |
| 63 | |
| 64 | // Initialise the server before becoming a daemon. If the process is |
| 65 | // started from a shell, this means any errors will be reported back to the |
| 66 | // user. |
| 67 | udp_daytime_server server(io_context); |
| 68 | |
| 69 | // Register signal handlers so that the daemon may be shut down. You may |
| 70 | // also want to register for other signals, such as SIGHUP to trigger a |
| 71 | // re-read of a configuration file. |
| 72 | boost::asio::signal_set signals(io_context, SIGINT, SIGTERM); |
| 73 | signals.async_wait( |
| 74 | [&](boost::system::error_code /*ec*/, int /*signo*/) |
| 75 | { |
| 76 | io_context.stop(); |
| 77 | }); |
| 78 | |
| 79 | // Inform the io_context that we are about to become a daemon. The |
| 80 | // io_context cleans up any internal resources, such as threads, that may |
| 81 | // interfere with forking. |
| 82 | io_context.notify_fork(boost::asio::io_context::fork_prepare); |
| 83 | |
| 84 | // Fork the process and have the parent exit. If the process was started |
| 85 | // from a shell, this returns control to the user. Forking a new process is |
| 86 | // also a prerequisite for the subsequent call to setsid(). |
| 87 | if (pid_t pid = fork()) |
| 88 | { |
| 89 | if (pid > 0) |
| 90 | { |
| 91 | // We're in the parent process and need to exit. |
| 92 | // |
| 93 | // When the exit() function is used, the program terminates without |
| 94 | // invoking local variables' destructors. Only global variables are |
| 95 | // destroyed. As the io_context object is a local variable, this means |
| 96 | // we do not have to call: |
| 97 | // |
| 98 | // io_context.notify_fork(boost::asio::io_context::fork_parent); |
| 99 | // |
| 100 | // However, this line should be added before each call to exit() if |
| 101 | // using a global io_context object. An additional call: |
| 102 | // |
| 103 | // io_context.notify_fork(boost::asio::io_context::fork_prepare); |
| 104 | // |
| 105 | // should also precede the second fork(). |
| 106 | exit(0); |
| 107 | } |
| 108 | else |
| 109 | { |
| 110 | syslog(LOG_ERR | LOG_USER, "First fork failed: %m"); |
| 111 | return 1; |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Make the process a new session leader. This detaches it from the |
nothing calls this directly
no test coverage detected