summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-07-31 10:30:08 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-07-31 10:30:08 -0500
commit4d8f3a663faf631b2976ef920d529c6230132d9e (patch)
tree3259654319a664b865f7fab42bca60595e72f2cb
parentbac7ea9a27aaad28239f646caeae77747d987776 (diff)
downloadtdebase-4d8f3a663faf631b2976ef920d529c6230132d9e.tar.gz
tdebase-4d8f3a663faf631b2976ef920d529c6230132d9e.zip
Prevent more than one instance of tdekbdledsync from starting on a given X11 display
This resolves Bug 1601
-rw-r--r--tdekbdledsync/main.cpp69
1 files changed, 64 insertions, 5 deletions
diff --git a/tdekbdledsync/main.cpp b/tdekbdledsync/main.cpp
index e48af2f53..a439ebd41 100644
--- a/tdekbdledsync/main.cpp
+++ b/tdekbdledsync/main.cpp
@@ -33,6 +33,7 @@ License along with tdekbdledsync. If not, see http://www.gnu.org/licenses/.
#include <linux/vt.h>
#include <linux/input.h>
#include <linux/uinput.h>
+#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
@@ -71,6 +72,9 @@ int keyboard_fds[MAX_KEYBOARDS];
Display* display = NULL;
+int lockfd = -1;
+char lockFileName[256];
+
// --------------------------------------------------------------------------------------
// Useful function from Stack Overflow
// http://stackoverflow.com/questions/874134/find-if-string-endswith-another-string-in-c
@@ -92,6 +96,34 @@ int str_ends_with(const char * str, const char * suffix) {
// --------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------
+// Useful function from Stack Overflow
+// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
+// --------------------------------------------------------------------------------------
+int tryGetLock(char const *lockName) {
+ mode_t m = umask( 0 );
+ int fd = open( lockName, O_RDWR|O_CREAT, 0666 );
+ umask( m );
+ if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 ) {
+ close( fd );
+ fd = -1;
+ }
+ return fd;
+}
+
+// --------------------------------------------------------------------------------------
+// Useful function from Stack Overflow
+// http://stackoverflow.com/questions/1599459/optimal-lock-file-method
+// --------------------------------------------------------------------------------------
+void releaseLock(int fd, char const *lockName) {
+ if( fd < 0 ) {
+ return;
+ }
+ remove( lockName );
+ close( fd );
+}
+
+
+// --------------------------------------------------------------------------------------
// Get the VT number X is running on
// (code taken from GDM, daemon/getvt.c, GPLv2+)
// --------------------------------------------------------------------------------------
@@ -254,6 +286,13 @@ int find_keyboards() {
return 0;
}
+void handle_sigterm(int signum) {
+ if (lockfd >= 0) {
+ releaseLock(lockfd, lockFileName);
+ }
+ exit(0);
+}
+
int main() {
int current_keyboard;
char name[256] = "Unknown";
@@ -276,6 +315,12 @@ int main() {
int evBase;
int errBase;
+ // Register cleanup handlers
+ struct sigaction action;
+ memset(&action, 0, sizeof(struct sigaction));
+ action.sa_handler = handle_sigterm;
+ sigaction(SIGTERM, &action, NULL);
+
// Open X11 display
display = XOpenDisplay(NULL);
if (!display) {
@@ -283,13 +328,22 @@ int main() {
return -1;
}
+ // Ensure only one process is running on a given display
+ sprintf(lockFileName, "/var/lock/tdekbdledsync-%s.lock", XDisplayString(display));
+ lockfd = tryGetLock(lockFileName);
+ if (lockfd < 0) {
+ printf ("[tdekbdledsync] Another instance of this program is already running on this X11 display!\n[tdekbdledsync] Lockfile detected at '%s'\n", lockFileName);
+ return -2;
+ }
+
// Set up Xkb extension
int i1, mn, mj;
mj = XkbMajorVersion;
mn = XkbMinorVersion;
if (!XkbQueryExtension(display, &i1, &evBase, &errBase, &mj, &mn)) {
printf("[tdekbdledsync] Server doesn't support a compatible XKB\n");
- return -2;
+ releaseLock(lockfd, lockFileName);
+ return -3;
}
XkbSelectEvents(display, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask);
@@ -309,7 +363,8 @@ int main() {
udev = udev_new();
if (!udev) {
printf("[tdekbdledsync] Cannot connect to udev interface\n");
- return -3;
+ releaseLock(lockfd, lockFileName);
+ return -4;
}
// Set up a udev monitor to monitor input devices
@@ -327,7 +382,8 @@ int main() {
find_keyboards();
if (keyboard_fd_num == 0) {
printf ("[tdekbdledsync] Could not find any usable keyboard(s)!\n");
- return -4;
+ releaseLock(lockfd, lockFileName);
+ return -5;
}
else {
fprintf(stderr, "[tdekbdledsync] Found %d keyboard(s)\n", keyboard_fd_num);
@@ -342,14 +398,16 @@ int main() {
// Get current active VT
if (ioctl(vt_fd, VT_GETSTATE, &vtstat)) {
fprintf(stderr, "[tdekbdledsync] Unable to get current VT!\n");
- return -5;
+ releaseLock(lockfd, lockFileName);
+ return -6;
}
if (x11_vt_num == vtstat.v_active) {
// Get Virtual Core keyboard status
if (XkbGetIndicatorState(display, XkbUseCoreKbd, &states) != Success) {
fprintf(stderr, "[tdekbdledsync] Unable to query X11 Virtual Core keyboard!\n");
- return -6;
+ releaseLock(lockfd, lockFileName);
+ return -7;
}
XkbGetState(display, XkbUseCoreKbd, &state);
@@ -440,5 +498,6 @@ int main() {
}
}
+ releaseLock(lockfd, lockFileName);
return 0;
}