[PATCH 1 of 2] Implemented detection of running instance on linux using a lock file
Wald Commits
scm-commit at wald.intevation.org
Mon Jul 14 12:48:50 CEST 2014
# HG changeset patch
# User Sascha Wilde <wilde at intevation.de>
# Date 1405334807 -7200
# Node ID 20ca946800033f3b104caccd2684059e265d90e8
# Parent 2c69298b418837eb02db957307c7bfe51d2b7f69
Implemented detection of running instance on linux using a lock file.
diff -r 2c69298b4188 -r 20ca94680003 common/CMakeLists.txt
--- a/common/CMakeLists.txt Thu Jul 10 19:16:21 2014 +0200
+++ b/common/CMakeLists.txt Mon Jul 14 12:46:47 2014 +0200
@@ -16,6 +16,7 @@
util.c
binverify.c
selftest.c
+ linuxlockfile.c
)
if(WIN32)
diff -r 2c69298b4188 -r 20ca94680003 common/linuxlockfile.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/common/linuxlockfile.c Mon Jul 14 12:46:47 2014 +0200
@@ -0,0 +1,72 @@
+#ifndef WIN32
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "logging.h"
+
+int
+open_lockfile(char *path)
+{
+ int fd;
+ char pidstr[20];
+ size_t pidstrlen;
+ struct flock lk;
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+ if (fd != -1)
+ {
+ /* Get an exclusive lock on the whole file. */
+ lk.l_type = F_WRLCK;
+ lk.l_whence = SEEK_SET;
+ lk.l_start = 0;
+ lk.l_len = 0;
+ if (fcntl(fd, F_SETLK, &lk) != -1)
+ {
+ /* FIXME: 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;
+ }
+ }
+ else
+ {
+ DEBUGPRINTF("Failed to open lock file: %s.\n", path);
+ }
+ return fd;
+}
+
+void
+close_lockfile(int fd)
+{
+ struct flock lk;
+
+ /* Delete the PID from file. */
+ /* We do this instead of trying to unlink the file. */
+ ftruncate(fd, 0);
+
+ /* Remove lock from the file. */
+ lk.l_type = F_UNLCK;
+ lk.l_whence = SEEK_SET;
+ lk.l_start = 0;
+ lk.l_len = 0;
+ if (fcntl(fd, F_SETLK, &lk) == -1)
+ {
+ /* Lock can not be removed?!? WTF? */
+ DEBUGPRINTF("Could not remove lock from pid file. STRANGE!\n");
+ }
+ close(fd);
+}
+
+#endif /* Not WIN32 */
diff -r 2c69298b4188 -r 20ca94680003 common/linuxlockfile.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/common/linuxlockfile.h Mon Jul 14 12:46:47 2014 +0200
@@ -0,0 +1,38 @@
+/**
+ * @file linuxlockfile.h
+ * @brief Linux specific functions for lock file handling.
+ * @details Functions to handle procsss specific lock files, these are
+ * only used on GNU Linux as on windows different mechanisms are
+ * utilized to ensure only a single instance runs at a time.
+ */
+
+#ifndef LINUXLOCKFILE_H
+#define LINUXLOCKFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief create a lockfile
+ * @details create and lock a lockfile containing the pid of the
+ * current process. fcntl is used for locking, to work in most cases
+ * (e.g. NFS).
+ * @param[in] path to the lockfile
+ * @returns the file descriptor of the lockfile or -1 on error
+ */
+int open_lockfile(char *path);
+
+/**
+ * @brief close a lockfile
+ * @details unlock and close a lockfile for the given file descriptor.
+ * @param[in] path to the lockfile
+ * @returns the file descriptor of the lockfile or -1 on error
+ */
+void close_lockfile(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -r 2c69298b4188 -r 20ca94680003 ui/mainwindow.cpp
--- a/ui/mainwindow.cpp Thu Jul 10 19:16:21 2014 +0200
+++ b/ui/mainwindow.cpp Mon Jul 14 12:46:47 2014 +0200
@@ -1172,6 +1172,7 @@
void MainWindow::closeApp()
{
+ ProcessHelp::cleanUp();
qApp->quit();
}
diff -r 2c69298b4188 -r 20ca94680003 ui/processhelp.h
--- a/ui/processhelp.h Thu Jul 10 19:16:21 2014 +0200
+++ b/ui/processhelp.h Mon Jul 14 12:46:47 2014 +0200
@@ -45,5 +45,11 @@
* @param [in] executableName executableName (without path and .exe extension)
*/
void activateWindowForProcess(const QString &executableName);
+
+/**
+* @brief Clean up internaly used infrastructure like pid/lock files.
+*/
+ void cleanUp(void);
}
+
#endif // PROCESSHELP_H
diff -r 2c69298b4188 -r 20ca94680003 ui/processhelp_linux.cpp
--- a/ui/processhelp_linux.cpp Thu Jul 10 19:16:21 2014 +0200
+++ b/ui/processhelp_linux.cpp Mon Jul 14 12:46:47 2014 +0200
@@ -8,6 +8,19 @@
#ifndef WIN32
#include "processhelp.h"
+#include "linuxlockfile.h"
+
+#include <fcntl.h>
+#include <semaphore.h>
+
+#include <QDebug>
+#include <QDir>
+#include <QStandardPaths>
+
+namespace ProcessHelp
+{
+ int lockFileFD = -1;
+}
const QList<int> ProcessHelp::getProcessesIdForName(const QString &processName) {
// TODO
@@ -16,8 +29,17 @@
}
bool ProcessHelp::otherProcessesExist(const QString &processName) {
- // TODO
- Q_UNUSED(processName);
+ // FIXME: We are using lock file semantics on GNU Linux so the
+ // name of this method is rather misleading.
+
+ QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
+ dataDir.mkpath(".");
+ QString lockFilePath = dataDir.filePath(processName + ".pid");
+ lockFileFD = open_lockfile(lockFilePath.toLocal8Bit().data());
+ if (lockFileFD == -1)
+ // Creating the lock file failed, so we assume another
+ // instance is runnning.
+ return true;
return false;
}
@@ -27,4 +49,8 @@
return;
}
+void ProcessHelp::cleanUp() {
+ close_lockfile(lockFileFD);
+}
+
#endif /* Not WIN32 */
diff -r 2c69298b4188 -r 20ca94680003 ui/processhelp_win.cpp
--- a/ui/processhelp_win.cpp Thu Jul 10 19:16:21 2014 +0200
+++ b/ui/processhelp_win.cpp Mon Jul 14 12:46:47 2014 +0200
@@ -130,5 +130,10 @@
}
SetForegroundWindow(winStruct.windowId);
}
+
+void ProcessHelp::cleanUp() {
+ // Nothing to do on Windows.
+ return;
+}
+
#endif // WIN32
-
More information about the Trustbridge-commits
mailing list