diff --git a/ndhc/arp.c b/ndhc/arp.c index 2487892..2feb67f 100644 --- a/ndhc/arp.c +++ b/ndhc/arp.c @@ -136,7 +136,7 @@ void arp_success(struct client_state_t *cs) if (client_config.quit_after_lease) exit(EXIT_SUCCESS); if (!client_config.foreground) - background(); + background(cs); } typedef uint32_t aliased_uint32_t __attribute__((__may_alias__)); diff --git a/ndhc/ndhc.c b/ndhc/ndhc.c index 20f0588..08a26f6 100644 --- a/ndhc/ndhc.c +++ b/ndhc/ndhc.c @@ -181,20 +181,6 @@ static void perform_release(void) cs.timeout = -1; } -static void setup_signals() -{ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - sigaddset(&mask, SIGUSR2); - sigaddset(&mask, SIGTERM); - if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) - suicide("sigprocmask failed"); - cs.signalFd = signalfd(-1, &mask, SFD_NONBLOCK); - if (cs.signalFd < 0) - suicide("signalfd failed"); -} - static void signal_dispatch() { int t, off = 0; @@ -234,7 +220,7 @@ static void do_work(void) cs.epollFd = epoll_create1(0); if (cs.epollFd == -1) suicide("epoll_create1 failed"); - epoll_add(&cs, cs.signalFd); + setup_signals(&cs); change_listen_mode(&cs, LM_RAW); handle_timeout(&cs); @@ -387,8 +373,6 @@ int main(int argc, char **argv) memcpy(client_config.clientid + 3, client_config.arp, 6); } - setup_signals(); - if (chdir(chroot_dir)) { printf("Failed to chdir(%s)!\n", chroot_dir); exit(EXIT_FAILURE); diff --git a/ndhc/sys.c b/ndhc/sys.c index 3f34130..1afca83 100644 --- a/ndhc/sys.c +++ b/ndhc/sys.c @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include "config.h" #include "log.h" #include "pidfile.h" @@ -11,14 +13,38 @@ char pidfile[MAX_PATH_LENGTH] = PID_FILE_DEFAULT; -void background(void) +void setup_signals(struct client_state_t *cs) +{ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + sigaddset(&mask, SIGUSR2); + sigaddset(&mask, SIGTERM); + if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) + suicide("sigprocmask failed"); + if (cs->signalFd >= 0) { + epoll_del(cs, cs->signalFd); + close(cs->signalFd); + } + cs->signalFd = signalfd(-1, &mask, SFD_NONBLOCK); + if (cs->signalFd < 0) + suicide("signalfd failed"); + epoll_add(cs, cs->signalFd); +} + +// @cs can be NULL +void background(struct client_state_t *cs) { static char called; - if (!called && daemon(0, 0) == -1) { - perror("fork"); - exit(EXIT_SUCCESS); + if (!called) { + called = 1; /* Do not fork again. */ + if (daemon(0, 0) == -1) { + perror("fork"); + exit(EXIT_SUCCESS); + } + if (cs) + setup_signals(cs); } - called = 1; /* Do not fork again. */ if (file_exists(pidfile, "w") == -1) { log_line("cannot open pidfile for write!"); } else @@ -46,3 +72,4 @@ void epoll_del(struct client_state_t *cs, int fd) if (r == -1) suicide("epoll_del failed %s", strerror(errno)); } + diff --git a/ndhc/sys.h b/ndhc/sys.h index d55df16..92c49d8 100644 --- a/ndhc/sys.h +++ b/ndhc/sys.h @@ -3,6 +3,7 @@ #include #include "ndhc-defines.h" +#include "config.h" static inline unsigned long long curms() { @@ -13,7 +14,8 @@ static inline unsigned long long curms() extern char pidfile[MAX_PATH_LENGTH]; -void background(void); +void setup_signals(struct client_state_t *cs); +void background(struct client_state_t *cs); void epoll_add(struct client_state_t *cs, int fd); void epoll_del(struct client_state_t *cs, int fd); diff --git a/ndhc/timeout.c b/ndhc/timeout.c index f186f6d..88dc3f3 100644 --- a/ndhc/timeout.c +++ b/ndhc/timeout.c @@ -22,7 +22,7 @@ static void init_selecting_timeout(struct client_state_t *cs) } else { if (client_config.background_if_no_lease) { log_line("No lease, going to background."); - background(); + background(cs); } else if (client_config.abort_if_no_lease) { log_line("No lease, failing."); exit(EXIT_FAILURE);