X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4f3c5f06ff074f4cd466e8d6b0c69e7b7ce7e142..adac097759c089b3d47f48c7756ace4f0b8df879:/src/unix/snglinst.cpp diff --git a/src/unix/snglinst.cpp b/src/unix/snglinst.cpp index 8b569946b1..d29268bbd3 100644 --- a/src/unix/snglinst.cpp +++ b/src/unix/snglinst.cpp @@ -44,8 +44,9 @@ #include #include -#include +#include // for S_I[RW]USR #include // for kill() +#include #ifdef HAVE_FCNTL #include @@ -57,15 +58,28 @@ #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()); } }