]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Daemonize sooner (code from bind9/named) (rebased)
authorFrancis Dupont <fdupont@isc.org>
Fri, 30 Sep 2016 23:35:37 +0000 (01:35 +0200)
committerFrancis Dupont <fdupont@isc.org>
Fri, 30 Sep 2016 23:35:37 +0000 (01:35 +0200)
client/dhc6.c
client/dhclient.c
includes/dhcpd.h
relay/dhcrelay.c
server/dhcpd.c

index c8d16e8a5fa6fd0e7045909d4ebcf558f2a20ae1..be604ac988a983b2829f76fe2bff6a5f036d8019 100644 (file)
@@ -1500,7 +1500,7 @@ start_init6(struct client_state *client)
        add_timeout(&tv, do_init6, client, NULL, NULL);
 
        if (nowait)
-               go_daemon();
+               detach();
 }
 
 /*
@@ -1544,7 +1544,7 @@ start_info_request6(struct client_state *client)
        add_timeout(&tv, do_info_request6, client, NULL, NULL);
 
        if (nowait)
-               go_daemon();
+               detach();
 }
 
 /*
@@ -1871,7 +1871,7 @@ do_init6(void *input)
                }
                /* Stop if and only if this is the last client. */
                if (stopping_finished())
-                       exit(2);
+                       finish(2);
                return;
        }
 
@@ -2176,7 +2176,7 @@ do_info_request6(void *input)
              case CHK_TIM_ALLOC_FAILURE:
                return;
              case CHK_TIM_MRD_EXCEEDED:
-               exit(2);
+               finish(2);
              case CHK_TIM_SUCCESS:
                break;
        }
@@ -2418,7 +2418,7 @@ do_release6(void *input)
        dhc6_lease_destroy(&client->active_lease, MDL);
        client->active_lease = NULL;
        if (stopping_finished())
-               exit(0);
+               finish(0);
 }
 
 /* status_log() just puts a status code into displayable form and logs it
@@ -4224,7 +4224,7 @@ reply_handler(struct packet *packet, struct client_state *client)
                client->active_lease = NULL;
                /* We should never wait for nothing!? */
                if (stopping_finished())
-                       exit(0);
+                       finish(0);
                return;
        }
 
@@ -4840,7 +4840,7 @@ start_bound(struct client_state *client)
                dhcp4o6_start();
 #endif
 
-       go_daemon();
+       detach();
 
        if (client->old_lease != NULL) {
                dhc6_lease_destroy(&client->old_lease, MDL);
@@ -5323,7 +5323,7 @@ dhc6_check_irt(struct client_state *client)
 #ifdef DHCP4o6
                if (!dhcpv4_over_dhcpv6)
 #endif
-               exit(0);
+               finish(0);
        }
 
        oc = lookup_option(&dhcpv6_universe, client->active_lease->options,
@@ -5382,7 +5382,7 @@ start_informed(struct client_state *client)
                dhcp4o6_start();
 #endif
 
-       go_daemon();
+       detach();
 
        if (client->old_lease != NULL) {
                dhc6_lease_destroy(&client->old_lease, MDL);
index f7486c6a754f741fecb2a2999d78778ab79a5970..caf80aecaa5f37a679c54ef2911aaa1b77bb4844 100644 (file)
@@ -84,6 +84,7 @@ u_int16_t remote_port = 0;
 int dhcp4o6_state = -1; /* -1 = stopped, 0 = polling, 1 = started */
 #endif
 int no_daemon = 0;
+int dfd[2] = { -1, -1 };
 struct string_list *client_env = NULL;
 int client_env_count = 0;
 int onetry = 0;
@@ -236,6 +237,51 @@ main(int argc, char **argv) {
        setlogmask(LOG_UPTO(LOG_INFO));
 #endif
 
+       /* Parse arguments changing no_daemon */
+       for (i = 1; i < argc; i++) {
+               if (!strcmp(argv[i], "-r")) {
+                       no_daemon = 1;
+               } else if (!strcmp(argv[i], "-x")) {
+                       no_daemon = 0;
+               } else if (!strcmp(argv[i], "-d")) {
+                       no_daemon = 1;
+               } else if (!strcmp(argv[i], "--version")) {
+                       const char vstring[] = "isc-dhclient-";
+                       IGNORE_RET(write(STDERR_FILENO, vstring,
+                                        strlen(vstring)));
+                       IGNORE_RET(write(STDERR_FILENO,
+                                        PACKAGE_VERSION,
+                                        strlen(PACKAGE_VERSION)));
+                       IGNORE_RET(write(STDERR_FILENO, "\n", 1));
+                       exit(0);
+               }
+       }
+       /* When not forbidden prepare to become a daemon */
+       if (!no_daemon) {
+               int pid;
+
+               if (pipe(dfd) == -1)
+                       log_fatal("Can't get pipe: %m");
+               if ((pid = fork ()) < 0)
+                       log_fatal("Can't fork daemon: %m");
+               if (pid != 0) {
+                       /* Parent: wait for the child to start */
+                       int n;
+
+                       (void) close(dfd[1]);
+                       do {
+                               char buf;
+
+                               n = read(dfd[0], &buf, 1);
+                               if (n == 1)
+                                       _exit((int)buf);
+                       } while (n == -1 && errno == EINTR);
+                       _exit(1);
+               }
+               /* Child */
+               (void) close(dfd[0]);
+       }
+
        /* Set up the isc and dns library managers */
        status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
                                     NULL, NULL);
@@ -260,7 +306,7 @@ main(int argc, char **argv) {
        for (i = 1; i < argc; i++) {
                if (!strcmp(argv[i], "-r")) {
                        release_mode = 1;
-                       no_daemon = 1;
+                       /* no_daemon = 1; */
 #ifdef DHCPv6
                } else if (!strcmp(argv[i], "-4")) {
                        if (local_family_set && local_family != AF_INET)
@@ -288,7 +334,7 @@ main(int argc, char **argv) {
 #endif /* DHCPv6 */
                } else if (!strcmp(argv[i], "-x")) { /* eXit, no release */
                        release_mode = 0;
-                       no_daemon = 0;
+                       /* no_daemon = 0; */
                        exit_mode = 1;
                } else if (!strcmp(argv[i], "-p")) {
                        if (++i == argc)
@@ -297,7 +343,7 @@ main(int argc, char **argv) {
                        log_debug("binding to user-specified port %d",
                                  ntohs(local_port));
                } else if (!strcmp(argv[i], "-d")) {
-                       no_daemon = 1;
+                       /* no_daemon = 1; */
                        quiet = 0;
                } else if (!strcmp(argv[i], "-pf")) {
                        if (++i == argc)
@@ -422,15 +468,6 @@ main(int argc, char **argv) {
                        std_dhcid = 1;
                } else if (!strcmp(argv[i], "-v")) {
                        quiet = 0;
-               } else if (!strcmp(argv[i], "--version")) {
-                       const char vstring[] = "isc-dhclient-";
-                       IGNORE_RET(write(STDERR_FILENO, vstring,
-                                        strlen(vstring)));
-                       IGNORE_RET(write(STDERR_FILENO,
-                                        PACKAGE_VERSION,
-                                        strlen(PACKAGE_VERSION)));
-                       IGNORE_RET(write(STDERR_FILENO, "\n", 1));
-                       exit(0);
                } else if (argv[i][0] == '-') {
                        usage("Unknown command: %s", argv[i]);
                } else if (interfaces_requested < 0) {
@@ -613,7 +650,7 @@ main(int argc, char **argv) {
                if (release_mode || (wanted_ia_na > 0) ||
                    wanted_ia_ta || wanted_ia_pd ||
                    (interfaces_requested != 1)) {
-                       usage("Stateless commnad: %s incompatibile with "
+                       usage("Stateless command: %s incompatibile with "
                              "other commands", "-S");
                }
 #if defined(DHCPv6) && defined(DHCP4o6)
@@ -621,7 +658,7 @@ main(int argc, char **argv) {
 #else
                run_stateless(exit_mode, 0);
 #endif
-               return 0;
+               finish(0);
        }
 
        /* Discover all the network interfaces. */
@@ -663,7 +700,7 @@ main(int argc, char **argv) {
                if (!persist) {
                        /* Nothing more to do. */
                        log_info("No broadcast interfaces found - exiting.");
-                       exit(0);
+                       finish(0);
                }
        } else if (!release_mode && !exit_mode) {
                /* Call the script with the list of interfaces. */
@@ -800,16 +837,16 @@ main(int argc, char **argv) {
        }
 
        if (exit_mode)
-               return 0;
+               finish(0);
        if (release_mode) {
 #ifndef DHCPv6
-               return 0;
+               finish(0);
 #else
                if ((local_family == AF_INET6) || dhcpv4_over_dhcpv6) {
                        if (onetry)
-                               return 0;
+                               finish(0);
                } else
-                       return 0;
+                       finish(0);
 #endif /* DHCPv6 */
        }
 
@@ -852,7 +889,7 @@ main(int argc, char **argv) {
        /* If we're not supposed to wait before getting the address,
           don't. */
        if (nowait)
-               go_daemon();
+               detach();
 
        /* If we're not going to daemonize, write the pid file
           now. */
@@ -963,7 +1000,7 @@ void run_stateless(int exit_mode, u_int16_t port)
        /* If we're not supposed to wait before getting the address,
           don't. */
        if (nowait)
-               go_daemon();
+               detach();
 
        /* If we're not going to daemonize, write the pid file
           now. */
@@ -1404,7 +1441,7 @@ void bind_lease (client)
                        if (!quiet)
                                log_info("Unable to obtain a lease on first "
                                         "try (declined).  Exiting.");
-                       exit(2);
+                       finish(2);
                } else {
                        state_init(client);
                        return;
@@ -1433,7 +1470,7 @@ void bind_lease (client)
              (long)(client->active->renewal - cur_time));
        client->state = S_BOUND;
        reinitialize_interfaces();
-       go_daemon();
+       detach();
 #if defined (NSUPDATE)
        if (client->config->do_forward_update)
                dhclient_schedule_updates(client, &client->active->address, 1);
@@ -2373,7 +2410,7 @@ void state_panic (cpp)
                                state_bound (client);
                            }
                            reinitialize_interfaces ();
-                           go_daemon ();
+                           detach ();
                            return;
                        }
                }
@@ -2413,7 +2450,7 @@ void state_panic (cpp)
                if (!quiet)
                        log_info ("Unable to obtain a lease on first try.%s",
                                  "  Exiting.");
-               exit (2);
+               finish(2);
        }
 
        log_info ("No working leases in persistent database - sleeping.");
@@ -2427,7 +2464,7 @@ void state_panic (cpp)
        tv.tv_usec = ((tv.tv_sec - cur_tv.tv_sec) > 1) ?
                        random() % 1000000 : cur_tv.tv_usec;
        add_timeout(&tv, state_init, client, 0, 0);
-       go_daemon ();
+       detach ();
 }
 
 void send_request (cpp)
@@ -4200,10 +4237,20 @@ int dhcp_option_ev_name (buf, buflen, option)
        return 1;
 }
 
-void go_daemon ()
+void finish (char ret)
 {
-       static int state = 0;
-       int pid;
+       if (no_daemon || dfd[0] == -1 || dfd[1] == -1)
+               exit((int)ret);
+       if (write(dfd[1], &ret, 1) != 1)
+               log_fatal("write to parent: %m");
+       (void) close(dfd[1]);
+       dfd[0] = dfd[1] = -1;
+       exit((int)ret);
+}
+
+void detach ()
+{
+       char buf = 0;
 
        /* Don't become a daemon if the user requested otherwise. */
        if (no_daemon) {
@@ -4212,18 +4259,18 @@ void go_daemon ()
        }
 
        /* Only do it once. */
-       if (state)
+       if (dfd[0] == -1 || dfd[1] == -1)
                return;
-       state = 1;
+
+       /* Signal parent we started successfully. */
+       if (write(dfd[1], &buf, 1) != 1)
+               log_fatal("write to parent: %m");
+       (void) close(dfd[1]);
+       dfd[0] = dfd[1] = -1;
 
        /* Stop logging to stderr... */
        log_perror = 0;
 
-       /* Become a daemon... */
-       if ((pid = fork ()) < 0)
-               log_fatal ("Can't fork daemon: %m");
-       else if (pid)
-               exit (0);
        /* Become session leader and get pid... */
        (void) setsid ();
 
@@ -4240,6 +4287,7 @@ void go_daemon ()
        write_client_pid_file ();
 
        IGNORE_RET (chdir("/"));
+
 }
 
 void write_client_pid_file ()
@@ -4376,7 +4424,7 @@ void do_release(client)
 
 #if defined(DHCPv6) && defined(DHCP4o6)
        if (dhcpv4_over_dhcpv6)
-               exit(0);
+               finish(0);
 #endif
 }
 
@@ -4507,7 +4555,7 @@ static void shutdown_exit (void *foo)
        /* get rid of the pid if we can */
        if (no_pid_file == ISC_FALSE)
                (void) unlink(path_dhclient_pid);
-       exit (0);
+       finish(0);
 }
 
 #if defined (NSUPDATE)
index 261714dcc91bd7fe39a72a2e52e822a535c68fab..a16b80db3244b6ea0f51bee2aeace0b547fca307 100644 (file)
@@ -2975,7 +2975,8 @@ void client_envadd (struct client_state *,
        __attribute__((__format__(__printf__,4,5)));
 
 struct client_lease *packet_to_lease (struct packet *, struct client_state *);
-void go_daemon (void);
+void finish (char);
+void detach (void);
 void write_client_pid_file (void);
 void client_location_changed (void);
 void do_release (struct client_state *);
index 344cee78474eb3549ae34742c4412898b9f1ba99..fd838be58187eb45ba784022e2dc0cf4bab2272c 100644 (file)
@@ -77,6 +77,9 @@ int missing_circuit_id = 0;   /* Circuit ID option in matching RAI option
                                   was missing. */
 int max_hop_count = 10;                /* Maximum hop count */
 
+int no_daemon = 0;
+int dfd[2] = { -1, -1 };
+
 #ifdef DHCPv6
        /* Force use of DHCPv6 interface-id option. */
 isc_boolean_t use_if_id = ISC_FALSE;
@@ -223,7 +226,7 @@ main(int argc, char **argv) {
        struct server_list *sp = NULL;
        char *service_local = NULL, *service_remote = NULL;
        u_int16_t port_local = 0, port_remote = 0;
-       int no_daemon = 0, quiet = 0;
+       int quiet = 0;
        int fd;
        int i;
 #ifdef DHCPv6
@@ -256,6 +259,50 @@ main(int argc, char **argv) {
        setlogmask(LOG_UPTO(LOG_INFO));
 #endif 
 
+       /* Parse arguments changing no_daemon */
+       for (i = 1; i < argc; i++) {
+               if (!strcmp(argv[i], "-d")) {
+                       no_daemon = 1;
+               } else if (!strcmp(argv[i], "--version")) {
+                       log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
+                       exit(0);
+               } else if (!strcmp(argv[i], "--help") ||
+                          !strcmp(argv[i], "-h")) {
+                       log_info(DHCRELAY_USAGE,
+#ifdef DHCPv6
+                                isc_file_basename(progname),
+#endif
+                                isc_file_basename(progname));
+                       exit(0);
+               }
+       }
+       /* When not forbidden prepare to become a daemon */
+       if (!no_daemon) {
+               int pid;
+
+               if (pipe(dfd) == -1)
+                       log_fatal("Can't get pipe: %m");
+               if ((pid = fork ()) < 0)
+                       log_fatal("Can't fork daemon: %m");
+               if (pid != 0) {
+                       /* Parent: wait for the child to start */
+                       int n;
+
+                       (void) close(dfd[1]);
+                       do {
+                               char buf;
+
+                               n = read(dfd[0], &buf, 1);
+                               if (n == 1)
+                                       _exit(0);
+                       } while (n == -1 && errno == EINTR);
+                       _exit(1);
+               }
+               /* Child */
+               (void) close(dfd[0]);
+       }
+
+
        /* Set up the isc and dns library managers */
        status = dhcp_context_create(DHCP_CONTEXT_PRE_DB | DHCP_CONTEXT_POST_DB,
                                     NULL, NULL);
@@ -288,7 +335,7 @@ main(int argc, char **argv) {
                        local_family = AF_INET6;
 #endif
                } else if (!strcmp(argv[i], "-d")) {
-                       no_daemon = 1;
+                       /* no_daemon = 1; */
                } else if (!strcmp(argv[i], "-q")) {
                        quiet = 1;
                        quiet_interface_discovery = 1;
@@ -481,17 +528,6 @@ main(int argc, char **argv) {
                        no_dhcrelay_pid = ISC_TRUE;
                } else if (!strcmp(argv[i], "--no-pid")) {
                        no_pid_file = ISC_TRUE;
-               } else if (!strcmp(argv[i], "--version")) {
-                       log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
-                       exit(0);
-               } else if (!strcmp(argv[i], "--help") ||
-                          !strcmp(argv[i], "-h")) {
-                       log_info(DHCRELAY_USAGE,
-#ifdef DHCPv6
-                                isc_file_basename(progname),
-#endif
-                                isc_file_basename(progname));
-                       exit(0);
                } else if (argv[i][0] == '-') {
                        usage("Unknown command: %s", argv[i]);
                } else {
@@ -647,17 +683,21 @@ main(int argc, char **argv) {
 
        /* Become a daemon... */
        if (!no_daemon) {
-               int pid;
+               char buf = 0;
                FILE *pf;
                int pfdesc;
 
                log_perror = 0;
 
-               if ((pid = fork()) < 0)
-                       log_fatal("Can't fork daemon: %m");
-               else if (pid)
-                       exit(0);
+               /* Signal parent we started successfully. */
+               if (dfd[0] != -1 && dfd[1] != -1) {
+                       if (write(dfd[1], &buf, 1) != 1)
+                               log_fatal("write to parent: %m");
+                       (void) close(dfd[1]);
+                       dfd[0] = dfd[1] = -1;
+               }
 
+               /* Create the pid file. */
                if (no_pid_file == ISC_FALSE) {
                        pfdesc = open(path_dhcrelay_pid,
                                      O_CREAT | O_TRUNC | O_WRONLY, 0644);
@@ -1865,12 +1905,19 @@ parse_allow_deny(struct option_cache **oc, struct parse *p, int i) {
 isc_result_t
 dhcp_set_control_state(control_object_state_t oldstate,
                       control_object_state_t newstate) {
+       char buf = 0;
+
        if (newstate != server_shutdown)
                return ISC_R_SUCCESS;
 
        if (no_pid_file == ISC_FALSE)
                (void) unlink(path_dhcrelay_pid);
 
+       if (!no_daemon && dfd[0] != -1 && dfd[1] != -1) {
+               IGNORE_RET(write(dfd[1], &buf, 1));
+               (void) close(dfd[1]);
+               dfd[0] = dfd[1] = -1;
+       }
        exit(0);
 }
 
index 43642823a81c6cb9c7a1798d7dd2baeb09419999..15f4370e321fe53b316f35e614121ed757ad9583 100644 (file)
@@ -220,6 +220,7 @@ main(int argc, char **argv) {
        char pbuf [20];
 #ifndef DEBUG
        int daemon = 1;
+       int dfd[2] = { -1, -1 };
 #endif
        int quiet = 0;
        char *server = (char *)0;
@@ -269,6 +270,68 @@ main(int argc, char **argv) {
         else if (fd != -1)
                 close(fd);
 
+       /* Parse arguments changing daemon */
+       for (i = 1; i < argc; i++) {
+               if (!strcmp (argv [i], "-f")) {
+#ifndef DEBUG
+                       daemon = 0;
+#endif
+               } else if (!strcmp (argv [i], "-d")) {
+#ifndef DEBUG
+                       daemon = 0;
+#endif
+               } else if (!strcmp (argv [i], "-t")) {
+#ifndef DEBUG
+                       daemon = 0;
+#endif
+               } else if (!strcmp (argv [i], "-T")) {
+#ifndef DEBUG
+                       daemon = 0;
+#endif
+               } else if (!strcmp (argv [i], "--version")) {
+                       const char vstring[] = "isc-dhcpd-";
+                       IGNORE_RET(write(STDERR_FILENO, vstring,
+                                        strlen(vstring)));
+                       IGNORE_RET(write(STDERR_FILENO,
+                                        PACKAGE_VERSION,
+                                        strlen(PACKAGE_VERSION)));
+                       IGNORE_RET(write(STDERR_FILENO, "\n", 1));
+                       exit (0);
+#ifdef TRACING
+               } else if (!strcmp (argv [i], "-play")) {
+#ifndef DEBUG
+                       daemon = 0;
+#endif
+#endif
+               }
+       }
+
+#ifndef DEBUG
+       /* When not forbidden prepare to become a daemon */
+       if (daemon) {
+               if (pipe(dfd) == -1)
+                       log_fatal("Can't get pipe: %m");
+               if ((pid = fork ()) < 0)
+                       log_fatal("Can't fork daemon: %m");
+               if (pid != 0) {
+                       /* Parent: wait for the child to start */
+                       int n;
+
+                       (void) close(dfd[1]);
+                       do {
+                               char buf;
+
+                               n = read(dfd[0], &buf, 1);
+                               if (n == 1)
+                                       _exit((int)buf);
+                       } while (n == -1 && errno == EINTR);
+                       _exit(1);
+               }
+               /* Child */
+               (void) close(dfd[0]);
+       }
+#endif
+
        /* Set up the isc and dns library managers */
        status = dhcp_context_create(DHCP_CONTEXT_PRE_DB,
                                     NULL, NULL);
@@ -304,11 +367,11 @@ main(int argc, char **argv) {
                               ntohs (local_port));
                } else if (!strcmp (argv [i], "-f")) {
 #ifndef DEBUG
-                       daemon = 0;
+                       /* daemon = 0; */
 #endif
                } else if (!strcmp (argv [i], "-d")) {
 #ifndef DEBUG
-                       daemon = 0;
+                       /* daemon = 0; */
 #endif
                        log_perror = -1;
                } else if (!strcmp (argv [i], "-s")) {
@@ -349,14 +412,14 @@ main(int argc, char **argv) {
                 } else if (!strcmp (argv [i], "-t")) {
                        /* test configurations only */
 #ifndef DEBUG
-                       daemon = 0;
+                       /* daemon = 0; */
 #endif
                        cftest = 1;
                        log_perror = -1;
                 } else if (!strcmp (argv [i], "-T")) {
                        /* test configurations and lease file only */
 #ifndef DEBUG
-                       daemon = 0;
+                       /* daemon = 0; */
 #endif
                        cftest = 1;
                        lftest = 1;
@@ -391,15 +454,6 @@ main(int argc, char **argv) {
                        dhcpv4_over_dhcpv6 = 1;
 #endif /* DHCP4o6 */
 #endif /* DHCPv6 */
-               } else if (!strcmp (argv [i], "--version")) {
-                       const char vstring[] = "isc-dhcpd-";
-                       IGNORE_RET(write(STDERR_FILENO, vstring,
-                                        strlen(vstring)));
-                       IGNORE_RET(write(STDERR_FILENO,
-                                        PACKAGE_VERSION,
-                                        strlen(PACKAGE_VERSION)));
-                       IGNORE_RET(write(STDERR_FILENO, "\n", 1));
-                       exit (0);
 #if defined (TRACING)
                } else if (!strcmp (argv [i], "-tf")) {
                        if (++i == argc)
@@ -845,14 +899,6 @@ main(int argc, char **argv) {
 #endif /* DHCPv6 */
 
 #ifndef DEBUG
-       if (daemon) {
-               /* First part of becoming a daemon... */
-               if ((pid = fork ()) < 0)
-                       log_fatal ("Can't fork daemon: %m");
-               else if (pid)
-                       exit (0);
-       }
        /*
         * Second part of dealing with pid files.  Now
         * that we have forked we can write our pid if
@@ -894,6 +940,15 @@ main(int argc, char **argv) {
                log_perror = 0;
 
        if (daemon) {
+               if (dfd[0] != -1 && dfd[1] != -1) {
+                       char buf = 0;
+
+                       if (write(dfd[1], &buf, 1) != 1)
+                               log_fatal("write to parent: %m");
+                       (void) close(dfd[1]);
+                       dfd[0] = dfd[1] = -1;
+               }
+
                /* Become session leader and get pid... */
                (void) setsid();