+ daemonize_start();
+ daemonize_complete();
+}
+
+static pid_t
+fork_and_wait_for_startup(int *fdp)
+{
+ int fds[2];
+ pid_t pid;
+
+ if (pipe(fds) < 0) {
+ ovs_fatal(errno, "pipe failed");
+ }
+
+ pid = fork();
+ if (pid > 0) {
+ /* Running in parent process. */
+ char c;
+
+ close(fds[1]);
+ fatal_signal_fork();
+ if (read(fds[0], &c, 1) != 1) {
+ int retval;
+ int status;
+
+ do {
+ retval = waitpid(pid, &status, 0);
+ } while (retval == -1 && errno == EINTR);
+
+ if (retval == pid
+ && WIFEXITED(status)
+ && WEXITSTATUS(status)) {
+ /* Child exited with an error. Convey the same error to
+ * our parent process as a courtesy. */
+ exit(WEXITSTATUS(status));
+ }
+
+ ovs_fatal(errno, "fork child failed to signal startup");
+ }
+ close(fds[0]);
+ *fdp = -1;
+ } else if (!pid) {
+ /* Running in child process. */
+ close(fds[0]);
+ time_postfork();
+ lockfile_postfork();
+ *fdp = fds[1];
+ } else {
+ ovs_fatal(errno, "could not fork");
+ }
+
+ return pid;
+}
+
+static void
+fork_notify_startup(int fd)
+{
+ if (fd != -1) {
+ size_t bytes_written;
+ int error;
+
+ error = write_fully(fd, "", 1, &bytes_written);
+ if (error) {
+ ovs_fatal(error, "could not write to pipe");
+ }
+
+ close(fd);
+ }
+}
+
+static bool
+should_restart(int status)
+{
+ if (WIFSIGNALED(status)) {
+ static const int error_signals[] = {
+ SIGABRT, SIGALRM, SIGBUS, SIGFPE, SIGILL, SIGPIPE, SIGSEGV,
+ SIGXCPU, SIGXFSZ
+ };
+
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(error_signals); i++) {
+ if (error_signals[i] == WTERMSIG(status)) {
+ return true;
+ }