From 0d35950715b2cd4bfd2f503fd62b37fd64d04785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Tue, 22 Sep 2020 17:48:17 +0200 Subject: [PATCH] Bind to a control socket So far using a lockfile, which kind of sucks. We're going to connect to DBus directly, so we'll see if it can't be used for our purposes in a simple way. --- CMakeLists.txt | 2 +- meson.build | 4 ++++ wdmtg.vala | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cdeae10..19bf901 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ vala_precompile (${project_VALA_SOURCES} OUTPUTS project_VALA_C HEADER ${PROJECT_NAME}.h SYMBOLS ${symbols_path} - PACKAGES gmodule-2.0 gio-2.0 gtk+-3.0 gee-0.8 sqlite3 x11) + PACKAGES posix gmodule-2.0 gio-2.0 gio-unix-2.0 gtk+-3.0 gee-0.8 sqlite3 x11) # Include Vala sources as header files, so they appear in the IDE # but CMake doesn't try to compile them directly diff --git a/meson.build b/meson.build index 7fd699d..f1c97b1 100644 --- a/meson.build +++ b/meson.build @@ -16,10 +16,14 @@ dependencies = [ dependency('gtk+-3.0'), dependency('gmodule-2.0'), dependency('gio-2.0'), + dependency('gio-unix-2.0'), dependency('gee-0.8'), dependency('sqlite3'), dependency('x11'), + # Only because of flock + meson.get_compiler('vala').find_library('posix'), + # Ours dependency('xext'), dependency('xextproto'), diff --git a/wdmtg.vala b/wdmtg.vala index 95646c7..c40ddd1 100644 --- a/wdmtg.vala +++ b/wdmtg.vala @@ -315,6 +315,45 @@ namespace Wdmtg { Config.PROJECT_NAME); DirUtils.create_with_parents (data_path, 0755); + // TODO: try exclusivity/invocation either via DBus directly, + // or via GApplication or GtkApplication: + // - GtkApplication calls Gtk.init automatically during "startup" signal, + // Gtk.init doesn't get command line args + // - "inhibiting" makes no sense, it can't be used for mere delays + // - actually, the "query-end" signal + // - should check whether it tries to exit cleanly + // - what is the session manager, do I have it? + // - "register-session" looks useful + // - GTK+ keeps the application running as long as it has windows, + // though I want to keep it running forever + // - g_application_hold(), perhaps + // - so maybe just use GApplication, that will provide more control + + // Bind to a control socket, also ensuring only one instance is running + var socket_path = Path.build_filename (data_path, "socket"); + + Posix.Flock fl = Posix.Flock () { + l_type = Posix.F_WRLCK, + l_start = 0, + l_whence = Posix.SEEK_SET, + l_len = 0 + }; + + var lk = FileStream.open (socket_path + ".lock", "w"); + if (Posix.fcntl (lk.fileno (), Posix.F_SETLK, &fl) < 0) + exit_fatal("failed to acquire lock: %s", Posix.errno.to_string ()); + FileUtils.unlink (socket_path); + + Socket socket; + try { + socket = new Socket (SocketFamily.UNIX, SocketType.STREAM, + SocketProtocol.DEFAULT); + socket.bind (new UnixSocketAddress (socket_path), true /* allow_reuse */); + socket.listen (); + } catch (Error e) { + exit_fatal ("%s: %s", socket_path, e.message); + } + Sqlite.Database db; var db_path = Path.build_filename (data_path, "db.sqlite"); int rc = Sqlite.Database.open (db_path, out db);