From: Roy Marples Date: Sun, 13 May 2007 12:28:54 +0000 (+0000) Subject: flock the pidfile and stop writing the parent pid to it so we're more robst. X-Git-Tag: v3.2.3~259 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=438263e0571dc945a5bf85445e4904c0f853cce6;p=thirdparty%2Fdhcpcd.git flock the pidfile and stop writing the parent pid to it so we're more robst. --- diff --git a/ChangeLog b/ChangeLog index cfacbff8..6ea14c64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +flock the pidfile and stop writing the parent pid to it so we're more robst. Enable DHCP_INFORM support via the -S option (requires -s ipaddr too) Use the DUID stored to create an RFC 4361 conformant client identifier if none is specified instead of just using the MAC address. diff --git a/client.c b/client.c index 59cadf90..d32f6298 100644 --- a/client.c +++ b/client.c @@ -19,12 +19,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef __linux__ +# define _XOPEN_SOURCE 500 /* needed for pwrite */ +#endif + #include #include #include #include #ifdef __linux__ -#include +# include #endif #include #include @@ -39,14 +43,14 @@ #include "config.h" #include "common.h" #ifdef ENABLE_ARP -#include "arp.h" +# include "arp.h" #endif #include "client.h" #include "configure.h" #include "dhcp.h" #include "dhcpcd.h" #ifdef ENABLE_INFO -#include "info.h" +# include "info.h" #endif #include "interface.h" #include "logger.h" @@ -98,18 +102,32 @@ memset (dhcp, 0, sizeof (dhcp_t)); \ } -static int daemonise (const char *pidfile) +static bool daemonise (int *pidfd) { + char pid[16]; + logger (LOG_DEBUG, "forking to background"); if (daemon (0, 0) < 0) { logger (LOG_ERR, "daemon: %s", strerror (errno)); - return -1; + return (false); } - make_pid (pidfile); + if (ftruncate (*pidfd, 0) == -1) { + logger (LOG_ERR, "ftruncate: %s", strerror (errno)); + return (false); + } + + snprintf (pid, sizeof (pid), "%u", getpid()); + if (pwrite (*pidfd, pid, strlen(pid), 0) != (ssize_t) strlen (pid)) { + logger (LOG_ERR, "pwrite: %s", strerror (errno)); + return (false); + } + + close (*pidfd); + *pidfd = -1; - return 0; + return (true); } static unsigned long random_xid (void) @@ -138,7 +156,7 @@ static unsigned long random_xid (void) /* This state machine is based on the one from udhcpc written by Russ Dill */ -int dhcp_run (const options_t *options) +int dhcp_run (const options_t *options, int *pidfd) { interface_t *iface; int mode = SOCKET_CLOSED; @@ -374,7 +392,7 @@ int dhcp_run (const options_t *options) iface->start_uptime = uptime (); if (! daemonised && options->daemonise) { - if ((daemonise (options->pidfile)) < 0) { + if ((daemonise (pidfd)) < 0) { retval = -1; goto eexit; } @@ -639,7 +657,7 @@ int dhcp_run (const options_t *options) } if (! daemonised && options->daemonise) { - if ((daemonise (options->pidfile)) < 0 ) { + if ((daemonise (pidfd)) < 0 ) { retval = EXIT_FAILURE; goto eexit; } diff --git a/client.h b/client.h index 88c460e1..406c8b79 100644 --- a/client.h +++ b/client.h @@ -24,6 +24,6 @@ #include "dhcpcd.h" -int dhcp_run (const options_t *options); +int dhcp_run (const options_t *options, int *pidfd); #endif diff --git a/dhcpcd.c b/dhcpcd.c index 5f264413..09e4b43e 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -24,6 +24,7 @@ #define _POSIX_SOURCE #endif +#include #include #include #include @@ -76,19 +77,6 @@ static pid_t read_pid(const char *pidfile) return pid; } -void make_pid (const char *pidfile) -{ - FILE *fp; - - if ((fp = fopen (pidfile, "w")) == NULL) { - logger (LOG_ERR, "fopen `%s': %s", pidfile, strerror (errno)); - return; - } - - fprintf (fp, "%u\n", getpid ()); - fclose (fp); -} - static void usage () { printf ("usage: "PACKAGE" [-adknpEGHMNRSY] [-c script] [-h hostame] [-i classID]\n" @@ -108,6 +96,7 @@ int main(int argc, char **argv) pid_t pid; int debug = 0; int i; + int pidfd; const struct option longopts[] = { {"arp", no_argument, NULL, 'a'}, @@ -404,10 +393,23 @@ int main(int argc, char **argv) exit (EXIT_FAILURE); } - make_pid (options.pidfile); + pidfd = open (options.pidfile, + O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0660); + if (pidfd == -1) { + logger (LOG_ERR, "open `%s': %s", options.pidfile, strerror (errno)); + exit (EXIT_FAILURE); + } + + /* Lock the file so that only one instance of dhcpcd runs on an interface */ + if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) { + logger (LOG_ERR, "flock `%s': %s", options.pidfile, strerror (errno)); + exit (EXIT_FAILURE); + } logger (LOG_INFO, PACKAGE " " VERSION " starting"); - if (dhcp_run (&options)) { + if (dhcp_run (&options, &pidfd)) { + if (pidfd > -1) + close (pidfd); unlink (options.pidfile); exit (EXIT_FAILURE); } diff --git a/dhcpcd.h b/dhcpcd.h index ff17bbc1..6b7af2d9 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -71,6 +71,4 @@ typedef struct options_t { char pidfile[PATH_MAX]; } options_t; -void make_pid (const char *pidfile); - #endif