]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
flock the pidfile and stop writing the parent pid to it so we're more robst.
authorRoy Marples <roy@marples.name>
Sun, 13 May 2007 12:28:54 +0000 (12:28 +0000)
committerRoy Marples <roy@marples.name>
Sun, 13 May 2007 12:28:54 +0000 (12:28 +0000)
ChangeLog
client.c
client.h
dhcpcd.c
dhcpcd.h

index cfacbff875a9187798a9fbbbd306bbffa6ce6d69..6ea14c647d9fae9b912db47209d619a5755746f8 100644 (file)
--- 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.
index 59cadf905bc1cc091eabd5cbd2284e5108ee21d5..d32f6298130c87a0a7585f5086fdbbe4b6f6bf22 100644 (file)
--- a/client.c
+++ b/client.c
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifdef __linux__
+# define _XOPEN_SOURCE 500 /* needed for pwrite */
+#endif
+
 #include <sys/types.h>
 #include <sys/select.h>
 #include <sys/time.h>
 #include <arpa/inet.h>
 #ifdef __linux__
-#include <netinet/ether.h>
+# include <netinet/ether.h>
 #endif
 #include <errno.h>
 #include <fcntl.h>
 #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"
        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;
                                                        }
index 88c460e17d469d24d48218874b2de5a9e22170c7..406c8b7987608f2062a428bcf34714d84de28d34 100644 (file)
--- 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
index 5f264413abac300c8d15a23d156fdb92c18ca3ec..09e4b43e51302738fe63f5eb6373efee462774c1 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -24,6 +24,7 @@
 #define _POSIX_SOURCE
 #endif
 
+#include <sys/file.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <arpa/inet.h>
@@ -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);
        }
index ff17bbc1715dd97654cec71d25e905c6bc2fefeb..6b7af2d949fa5fa0d2b16b330453df54ec4a2e21 100644 (file)
--- 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