Enlightenment CVS committal

Author  : kwo
Project : e16
Module  : epplets

Dir     : e16/epplets/api


Modified Files:
        epplet.c 


Log Message:
Fix epplet instance counting in cases where a leftover lock file exists
which contains the pid of a running process that is not the epplet that
created it.  
For the fix to work it is required that the lock file can be locked
using fcntl. If it cannot be locked (e.g. home dir on NFS mount) the
code falls back to the old behavior.

===================================================================
RCS file: /cvsroot/enlightenment/e16/epplets/api/epplet.c,v
retrieving revision 1.131
retrieving revision 1.132
diff -u -3 -r1.131 -r1.132
--- epplet.c    11 Feb 2005 04:29:17 -0000      1.131
+++ epplet.c    5 Feb 2006 09:27:03 -0000       1.132
@@ -1,6 +1,7 @@
 #include "config.h"
 #include "epplet.h"
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/utsname.h>
 #include <signal.h>
 #include <sys/wait.h>
@@ -5495,8 +5496,9 @@
 Epplet_find_instance(char *name)
 {
    struct stat         st;
+   struct flock        fl;
    char                s[1024], *tmpdir;
-   int                 i = 0, fd;
+   int                 i, fd, err, exists, locked;
    pid_t               pid;
 
    /* Find E dir */
@@ -5552,51 +5554,76 @@
 
    /* Pick our instance number.  255 is the max to avoid infinite loops, which 
could be caused by
     * lack of insert permissions in the config directory. */
+   fl.l_type = F_WRLCK;
+   fl.l_whence = SEEK_SET;
+   fl.l_start = fl.l_len = 0;
+   locked = 0;
+
    for (i = 1; i < 256; i++)
      {
        Esnprintf(s, sizeof(s), "%s/.lock_%i", conf_dir, i);
-       if (stat(s, &st) >= 0)
+
+       exists = stat(s, &st) == 0;
+
+       if (exists)
+          fd = open(s, (O_RDWR | O_CREAT), 0600);
+       else
+          fd = open(s, (O_WRONLY | O_EXCL | O_CREAT), 0600);
+       if (fd < 0)
+          continue;
+       for (;;)
          {
-            /* Lock file exists.  Read from it. */
-            if ((fd = open(s, O_RDONLY)) < 0)
-              {
-                 /* Either it's there and we can't read it, or it's gone now.  
Next! */
-                 fprintf(stderr, "Unable to read lock file %s -- %s\n", s,
-                         strerror(errno));
-                 continue;
-              }
-            if ((read(fd, &pid, sizeof(pid_t))) < ((int)sizeof(pid_t)))
-              {
-                 /* We didn't get enough bytes.  Next! */
-                 fprintf(stderr,
+            err = fcntl(fd, F_SETLK, &fl);
+            if (err != EINTR)
+               break;
+         }
+       if (err == 0)
+         {
+            /* Locking succeeded, file is open for writing */
+            locked = 1;
+            break;
+         }
+
+       if (!exists)
+         {
+            /* Locking failed, but file was successfully created with O_EXCL */
+            break;
+         }
+
+       /* Check pid */
+       if ((read(fd, &pid, sizeof(pid_t))) < ((int)sizeof(pid_t)))
+         {
+            /* We didn't get enough bytes.  Next! */
+            fprintf(stderr,
                          "Read attempt for lock file %s failed -- %s\n", s,
                          strerror(errno));
-                 continue;
-              }
             close(fd);
-            if (pid <= 0)
-              {
-                 /* We got a bogus process ID.  Next! */
-                 fprintf(stderr,
-                         "Lock file %s contained a bogus process ID (%lu)\n",
-                         s, (unsigned long)pid);
-                 continue;
-              }
-            if ((kill(pid, 0) == 0) || (errno != ESRCH))
-              {
-                 /* The process exists.  Next! */
-                 continue;
-              }
-            /* Okay, looks like a stale lockfile at this point.  Remove it. */
-            if ((unlink(s)) != 0)
-              {
-                 /* Removal failed.  Next! */
-                 fprintf(stderr,
-                         "Unable to remove stale lock file %s -- %s.  Please 
remove it manually.\n",
-                         s, strerror(errno));
-                 continue;
-              }
+            continue;
+         }
+       close(fd);
+       if (pid <= 0)
+         {
+            /* We got a bogus process ID.  Next! */
+            fprintf(stderr,
+                    "Lock file %s contained a bogus process ID (%lu)\n",
+                    s, (unsigned long)pid);
+            continue;
+         }
+       if ((kill(pid, 0) == 0) || (errno != ESRCH))
+         {
+            /* The process exists.  Next! */
+            continue;
+         }
+       /* Okay, looks like a stale lockfile at this point.  Remove it. */
+       if ((unlink(s)) != 0)
+         {
+            /* Removal failed.  Next! */
+            fprintf(stderr,
+                    "Unable to remove stale lock file %s -- %s.  Please remove 
it manually.\n",
+                    s, strerror(errno));
+            continue;
          }
+
        srand(getpid());
        usleep((rand() & 0xfffff));
        if ((fd = open(s, (O_WRONLY | O_EXCL | O_CREAT), 0600)) < 0)
@@ -5604,16 +5631,20 @@
             /* Apparently another process just came in under us and created 
it.  Next! */
             continue;
          }
-       pid = getpid();
-       write(fd, &pid, sizeof(pid_t));         /* Not sure how best to deal 
with write errors here */
-       close(fd);
-       /* If we made it here, we've just written the lock file and saved it.  
We have our instance
+       /* If we made it here, we've just created the lock file.  We have our 
instance
         * number, so exit the loop. */
        break;
      }
 
-   /* Anything this high is probably an error. */
-   if (i >= 255)
+   if (i < 256)
+     {
+       pid = getpid();
+       write(fd, &pid, sizeof(pid_t));         /* Not sure how best to deal 
with write errors here */
+       /* If locked do not close fd, otherwise lock is lost */
+       if (!locked)
+          close(fd);
+     }
+   else
      {
        i = 1;
      }




-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=103432&bid=230486&dat=121642
_______________________________________________
enlightenment-cvs mailing list
enlightenment-cvs@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs

Reply via email to