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
This commit is contained in:
Jiří Klimeš
2012-10-26 14:13:59 +02:00
committed by Dan Williams
parent 3c9ba7d895
commit cf74d74fcc

View File

@@ -35,11 +35,20 @@
#define SD_PATH "/org/freedesktop/login1" #define SD_PATH "/org/freedesktop/login1"
#define SD_INTERFACE "org.freedesktop.login1.Manager" #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 { struct _NMSleepMonitor {
GObject parent_instance; GObject parent_instance;
#if defined(IS_GDBUS_UNIXFD_AVAILABLE)
GDBusProxy *sd_proxy; GDBusProxy *sd_proxy;
#else
DBusGProxy *sd_proxy;
#endif
gint inhibit_fd; 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 static void
inhibit_done (GObject *source, inhibit_done (GObject *source,
GAsyncResult *result, GAsyncResult *result,
@@ -110,18 +133,6 @@ take_inhibitor (NMSleepMonitor *self)
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 static void
signal_cb (GDBusProxy *proxy, signal_cb (GDBusProxy *proxy,
const gchar *sendername, const gchar *sendername,
@@ -148,17 +159,153 @@ signal_cb (GDBusProxy *proxy,
} }
static void static void
nm_sleep_monitor_init (NMSleepMonitor *self) sleep_setup (NMSleepMonitor *self)
{ {
GDBusConnection *bus; GDBusConnection *bus;
self->inhibit_fd = -1;
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
self->sd_proxy = g_dbus_proxy_new_sync (bus, 0, NULL, self->sd_proxy = g_dbus_proxy_new_sync (bus, 0, NULL,
SD_NAME, SD_PATH, SD_INTERFACE, SD_NAME, SD_PATH, SD_INTERFACE,
NULL, NULL); NULL, NULL);
g_object_unref (bus); g_object_unref (bus);
g_signal_connect (self->sd_proxy, "g-signal", G_CALLBACK (signal_cb), self); 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); take_inhibitor (self);
} }