From cf74d74fcceabb029a14ef7d8b12aae6cc28ace2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Fri, 26 Oct 2012 14:13:59 +0200 Subject: [PATCH] sleep-monitor: make the systemd's sleep also work for GLib < 2.30 GDBus is only available from glib 2.26 and GUnixFDList from glib 2.30 --- src/nm-sleep-monitor-systemd.c | 175 ++++++++++++++++++++++++++++++--- 1 file changed, 161 insertions(+), 14 deletions(-) diff --git a/src/nm-sleep-monitor-systemd.c b/src/nm-sleep-monitor-systemd.c index 70adc8938..576cb1413 100644 --- a/src/nm-sleep-monitor-systemd.c +++ b/src/nm-sleep-monitor-systemd.c @@ -35,11 +35,20 @@ #define SD_PATH "/org/freedesktop/login1" #define SD_INTERFACE "org.freedesktop.login1.Manager" +/* Do we have GDBus (glib >= 2.26) and GUnixFDList (glib >= 2.30) support ? */ +#if GLIB_CHECK_VERSION(2,30,0) +#define IS_GDBUS_UNIXFD_AVAILABLE 1 +#endif + struct _NMSleepMonitor { GObject parent_instance; +#if defined(IS_GDBUS_UNIXFD_AVAILABLE) GDBusProxy *sd_proxy; +#else + DBusGProxy *sd_proxy; +#endif gint inhibit_fd; }; @@ -62,6 +71,20 @@ G_DEFINE_TYPE (NMSleepMonitor, nm_sleep_monitor, G_TYPE_OBJECT); /********************************************************************/ +static gboolean +drop_inhibitor (NMSleepMonitor *self) +{ + if (self->inhibit_fd >= 0) { + nm_log_dbg (LOGD_SUSPEND, "Dropping systemd sleep inhibitor"); + close (self->inhibit_fd); + self->inhibit_fd = -1; + return TRUE; + } + return FALSE; +} + +#if defined(IS_GDBUS_UNIXFD_AVAILABLE) +/* Great! We have GDBus (glib >= 2.26) and GUnixFDList (glib >= 2.30) */ static void inhibit_done (GObject *source, GAsyncResult *result, @@ -110,18 +133,6 @@ take_inhibitor (NMSleepMonitor *self) self); } -static gboolean -drop_inhibitor (NMSleepMonitor *self) -{ - if (self->inhibit_fd >= 0) { - nm_log_dbg (LOGD_SUSPEND, "Dropping systemd sleep inhibitor"); - close (self->inhibit_fd); - self->inhibit_fd = -1; - return TRUE; - } - return FALSE; -} - static void signal_cb (GDBusProxy *proxy, const gchar *sendername, @@ -148,17 +159,153 @@ signal_cb (GDBusProxy *proxy, } static void -nm_sleep_monitor_init (NMSleepMonitor *self) +sleep_setup (NMSleepMonitor *self) { GDBusConnection *bus; - self->inhibit_fd = -1; bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); self->sd_proxy = g_dbus_proxy_new_sync (bus, 0, NULL, SD_NAME, SD_PATH, SD_INTERFACE, NULL, NULL); g_object_unref (bus); g_signal_connect (self->sd_proxy, "g-signal", G_CALLBACK (signal_cb), self); +} + +#else + +/* GDBus nor GUnixFDList available. We have to get by with dbus-glib and libdbus */ +static void +inhibit_done (DBusPendingCall *pending, + gpointer user_data) +{ + NMSleepMonitor *self = user_data; + DBusMessage *reply; + DBusError error; + int mtype; + + dbus_error_init (&error); + reply = dbus_pending_call_steal_reply (pending); + g_assert (reply); + + mtype = dbus_message_get_type (reply); + switch (mtype) { + case DBUS_MESSAGE_TYPE_ERROR: + dbus_set_error_from_message (&error, reply); + nm_log_warn (LOGD_SUSPEND, "Inhibit() failed: %s", error.message ? error.message : "unknown"); + break; + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + if (!dbus_message_get_args (reply, + &error, + DBUS_TYPE_UNIX_FD, &self->inhibit_fd, + DBUS_TYPE_INVALID)) { + nm_log_warn (LOGD_SUSPEND, "Inhibit() reply parsing failed: %s", + error.message ? error.message : "unknown"); + break; + } + nm_log_dbg (LOGD_SUSPEND, "Inhibitor fd is %d", self->inhibit_fd); + break; + default: + nm_log_warn (LOGD_SUSPEND, "Invalid Inhibit() reply message type %d", mtype); + break; + } + + dbus_message_unref (reply); + dbus_error_free (&error); +} + +static void +take_inhibitor (NMSleepMonitor *self) +{ + NMDBusManager *dbus_mgr; + DBusConnection *bus; + DBusMessage *message = NULL; + DBusPendingCall *pending = NULL; + const char *arg_what = "sleep"; + const char *arg_who = g_get_user_name (); + const char *arg_why = "inhibited"; + const char *arg_mode = "delay"; + + g_assert (self->inhibit_fd == -1); + + nm_log_dbg (LOGD_SUSPEND, "Taking systemd sleep inhibitor"); + + dbus_mgr = nm_dbus_manager_get (); + bus = nm_dbus_manager_get_dbus_connection (dbus_mgr); + g_assert (bus); + g_object_unref (dbus_mgr); + + if (!(message = dbus_message_new_method_call (SD_NAME, + SD_PATH, + SD_INTERFACE, + "Inhibit"))) { + nm_log_warn (LOGD_SUSPEND, "Unable to call Inhibit()"); + return; + } + if (!dbus_message_append_args (message, + DBUS_TYPE_STRING, &arg_what, + DBUS_TYPE_STRING, &arg_who, + DBUS_TYPE_STRING, &arg_why, + DBUS_TYPE_STRING, &arg_mode, + DBUS_TYPE_INVALID)) { + nm_log_warn (LOGD_SUSPEND, "Unable to call Inhibit()"); + goto done; + } + + if (!dbus_connection_send_with_reply (bus, message, &pending, -1)) + goto done; + + if (!dbus_pending_call_set_notify (pending, inhibit_done, self, NULL)) { + dbus_pending_call_cancel (pending); + dbus_pending_call_unref (pending); + } + +done: + if (message) + dbus_message_unref (message); +} + +static void +signal_cb (DBusGProxy *proxy, gboolean about_to_suspend, gpointer data) +{ + NMSleepMonitor *self = data; + + nm_log_dbg (LOGD_SUSPEND, "Received PrepareForSleep signal: %d", about_to_suspend); + + if (about_to_suspend) { + g_signal_emit (self, signals[SLEEPING], 0); + drop_inhibitor (self); + } else { + take_inhibitor (self); + g_signal_emit (self, signals[RESUMING], 0); + } +} + +static void +sleep_setup (NMSleepMonitor *self) +{ + NMDBusManager *dbus_mgr; + DBusGConnection *bus; + + dbus_mgr = nm_dbus_manager_get (); + bus = nm_dbus_manager_get_connection (dbus_mgr); + self->sd_proxy = dbus_g_proxy_new_for_name (bus, SD_NAME, SD_PATH, SD_INTERFACE); + g_object_unref (dbus_mgr); + + if (self->sd_proxy) { + dbus_g_proxy_add_signal (self->sd_proxy, "PrepareForSleep", G_TYPE_BOOLEAN, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (self->sd_proxy, "PrepareForSleep", + G_CALLBACK (signal_cb), + self, NULL); + } else + nm_log_warn (LOGD_SUSPEND, "could not initialize systemd-logind D-Bus proxy"); +} +#endif /* IS_GDBUS_UNIXFD_AVAILABLE */ + +static void +nm_sleep_monitor_init (NMSleepMonitor *self) +{ + self->inhibit_fd = -1; + sleep_setup (self); take_inhibitor (self); }