diff common/linuxlockfile.c @ 1332:8362e30f7b55

(issue139) Check that pid is not running if the lock can be aquired If the lock on the lockfile can be aquired it might still be possible that another process is running. So we read the pid from the lockfile and check if another process with the same installation prefix as us is running.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 15 Oct 2014 14:19:46 +0200
parents 7ea3a4c0e2ae
children 5d7b1650de1f
line wrap: on
line diff
--- a/common/linuxlockfile.c	Wed Oct 15 13:24:59 2014 +0200
+++ b/common/linuxlockfile.c	Wed Oct 15 14:19:46 2014 +0200
@@ -12,8 +12,11 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <string.h>
 
 #include "logging.h"
+#include "util.h"
+#include "strhelp.h"
 
 int
 open_lockfile(char *path)
@@ -30,23 +33,55 @@
       lk.l_whence = SEEK_SET;
       lk.l_start = 0;
       lk.l_len = 0;
+      fcntl(fd, F_SETLK, &lk);
       if (fcntl(fd, F_SETLK, &lk) != -1)
-        {
-          /* FIXME (issue139): For extra security we should check if there is
-             already a pid in the file.  If so we should check in
-             /proc/$PID if there is still a process of the same name
-             as ours running... */
-          ftruncate(fd, 0);
-          pidstrlen = (size_t)snprintf(pidstr, sizeof(pidstr), "%d", getpid());
-          write(fd, pidstr, pidstrlen);
-        }
-      else
-        {
-          /* Lock can not be acquired.  Bail out... */
-          close(fd);
-          DEBUGPRINTF("Could not get an exclusive lock on %s.\n", path);
-          return -1;
-        }
+         {
+           char oldpid[20];
+           FILE *f = fopen(path, "r");
+           size_t bytes_read;
+           if (f)
+             {
+               bytes_read = fread(oldpid, 1, sizeof(oldpid), f);
+               if (bytes_read)
+                 {
+                   char *oldPath,
+                        *newPath;
+                   if (bytes_read == sizeof(oldpid))
+                     {
+                       ERRORPRINTF ("Bad information in pidfile\n");
+                     }
+                   else
+                     {
+                       oldpid[bytes_read] = '\0';
+                       oldPath = get_proc_install_dir(oldpid);
+                       newPath = get_install_dir();
+                       if (oldPath && newPath && strcmp(oldPath, newPath) == 0)
+                         {
+                           DEBUGPRINTF("Got lock but process from %s is still"
+                                       "running.\n", oldPath);
+                           xfree(oldPath);
+                           xfree(newPath);
+                           return -1;
+                         }
+                       xfree(oldPath);
+                       xfree(newPath);
+                     }
+                 }
+               fclose(f);
+             }
+
+           ftruncate(fd, 0);
+           pidstrlen = (size_t)snprintf(pidstr, sizeof(pidstr), "%d",
+                                        getpid());
+           write(fd, pidstr, pidstrlen);
+         }
+       else
+         {
+           /* Lock can not be acquired.  Bail out... */
+           close(fd);
+           DEBUGPRINTF("Could not get an exclusive lock on %s.\n", path);
+           return -1;
+         }
     }
   else
     {

http://wald.intevation.org/projects/trustbridge/