]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/snglinst.cpp
no significant changes
[wxWidgets.git] / src / unix / snglinst.cpp
index 8b569946b165579cd9332fea966fc06ad57a2678..d29268bbd3d9b096be9458448907a9c45aa0ad91 100644 (file)
@@ -44,8 +44,9 @@
 
 #include <unistd.h>
 #include <sys/types.h>
-#include <sys/stat.h>
+#include <sys/stat.h>           // for S_I[RW]USR
 #include <signal.h>             // for kill()
+#include <errno.h>
 
 #ifdef HAVE_FCNTL
     #include <fcntl.h>
 #endif // fcntl()/flock()
 
 // ----------------------------------------------------------------------------
-// private functions: (exclusively) lock/unlock the file
+// constants
 // ----------------------------------------------------------------------------
 
+// argument of wxLockFile()
 enum LockOperation
 {
     LOCK,
     UNLOCK
 };
 
+// return value of CreateLockFile()
+enum LockResult
+{
+    LOCK_ERROR = -1,
+    LOCK_EXISTS,
+    LOCK_CREATED
+};
+
+// ----------------------------------------------------------------------------
+// private functions: (exclusively) lock/unlock the file
+// ----------------------------------------------------------------------------
+
 #ifdef HAVE_FCNTL
 
 static int wxLockFile(int fd, LockOperation lock)
@@ -115,7 +129,7 @@ public:
 
 private:
     // try to create and lock the file
-    bool CreateLockFile();
+    LockResult CreateLockFile();
 
     // unlock and remove the lock file
     void Unlock();
@@ -134,17 +148,18 @@ private:
 // wxSingleInstanceCheckerImpl implementation
 // ============================================================================
 
-bool wxSingleInstanceCheckerImpl::CreateLockFile()
+LockResult wxSingleInstanceCheckerImpl::CreateLockFile()
 {
     // try to open the file
     m_fdLock = open(m_nameLock,
                     O_WRONLY | O_CREAT | O_EXCL,
-                    S_IREAD | S_IWRITE);
+                    S_IRUSR | S_IWUSR);
 
     if ( m_fdLock != -1 )
     {
         // try to lock it
-        if ( wxLockFile(m_fdLock, LOCK) == 0 )
+        int rc = wxLockFile(m_fdLock, LOCK);
+        if ( rc == 0 )
         {
             // fine, we have the exclusive lock to the file, write our PID
             // into it
@@ -152,7 +167,7 @@ bool wxSingleInstanceCheckerImpl::CreateLockFile()
 
             // use char here, not wxChar!
             char buf[256]; // enough for any PID size
-            int len = sprintf(buf, "%d", m_pidLocker) + 1;
+            int len = sprintf(buf, "%d", (int)m_pidLocker) + 1;
 
             if ( write(m_fdLock, buf, len) != len )
             {
@@ -161,33 +176,55 @@ bool wxSingleInstanceCheckerImpl::CreateLockFile()
 
                 Unlock();
 
-                return FALSE;
+                return LOCK_ERROR;
             }
 
             fsync(m_fdLock);
 
-            return TRUE;
+            return LOCK_CREATED;
         }
+        else // failure: see what exactly happened
+        {
+            close(m_fdLock);
+            m_fdLock = -1;
 
-        // couldn't lock: this might have happened because of a race
-        // condition: maybe another instance opened and locked the file
-        // between our calls to open() and flock()
-        close(m_fdLock);
-        m_fdLock = -1;
+            if ( rc != EACCES && rc != EAGAIN )
+            {
+                wxLogSysError(_("Failed to lock the lock file '%s'"),
+                              m_nameLock.c_str());
+
+                unlink(m_nameLock);
+
+                return LOCK_ERROR;
+            }
+            //else: couldn't lock because the lock is held by another process:
+            //      this might have happened because of a race condition:
+            //      maybe another instance opened and locked the file between
+            //      our calls to open() and flock(), so don't give an error
+        }
     }
 
     // we didn't create and lock the file
-    return FALSE;
+    return LOCK_EXISTS;
 }
 
 bool wxSingleInstanceCheckerImpl::Create(const wxString& name)
 {
     m_nameLock = name;
 
-    if ( CreateLockFile() )
+    switch ( CreateLockFile() )
     {
-        // nothing more to do
-        return TRUE;
+        case LOCK_EXISTS:
+            // there is a lock file, check below if it is still valid
+            break;
+
+        case LOCK_CREATED:
+            // nothing more to do
+            return TRUE;
+
+        case LOCK_ERROR:
+            // oops...
+            return FALSE;
     }
 
     // try to open the file for reading and get the PID of the process
@@ -217,7 +254,7 @@ bool wxSingleInstanceCheckerImpl::Create(const wxString& name)
     }
     else
     {
-        if ( sscanf(buf, "%d", &m_pidLocker) == 1 )
+        if ( sscanf(buf, "%d", (int *)&m_pidLocker) == 1 )
         {
             if ( kill(m_pidLocker, 0) != 0 )
             {
@@ -241,7 +278,7 @@ bool wxSingleInstanceCheckerImpl::Create(const wxString& name)
         }
         else
         {
-            wxLogWarning(_("Invalid lock file '%s'."));
+            wxLogWarning(_("Invalid lock file '%s'."), name.c_str());
         }
     }