summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2012-07-11 15:06:04 +0100
committerRichard Hughes <richard@hughsie.com>2012-07-11 18:11:39 +0100
commit44189f8129edff56668cad6846579adc0e64f8f3 (patch)
treecd59904458b38f983769ddcf64837eeb24422219
parent7bad068a2d9fbbd509d0a53bcf6c2ffde6a4ef77 (diff)
Use systemd for suspend and hibernate
When running under systemd, call into systemd for suspend and hibernate instead of pm-utils. To capture resume events, install a small script that gets executed by systemd after resume and sends a dbus signal back to upower. To make this work, the upower backends gain a new signal, ::resuming, that they can optionally emit to signal that a resume happened. Backends opt in to this by returning TRUE from up_backend_emits_resuming(). In this case, upower doesn't assume the sleep command to block until resume, but instead waits for the ::resuming signal from the backend. The only backend that uses this mechanism is the linux backend when built with systemd support. Signed-off-by: Richard Hughes <richard@hughsie.com>
-rw-r--r--configure.ac57
-rw-r--r--src/Makefile.am12
-rw-r--r--src/dummy/up-backend.c6
-rw-r--r--src/freebsd/up-backend.c6
-rw-r--r--src/linux/Makefile.am3
-rw-r--r--src/linux/up-backend.c67
-rwxr-xr-xsrc/notify-upower.sh6
-rw-r--r--src/openbsd/up-backend.c6
-rw-r--r--src/up-backend.h2
-rw-r--r--src/up-daemon.c61
10 files changed, 194 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac
index 311c6f2..8d8710c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -176,6 +176,55 @@ fi
176 176
177PKG_CHECK_MODULES(GIO, [gio-2.0 >= 2.16.1]) 177PKG_CHECK_MODULES(GIO, [gio-2.0 >= 2.16.1])
178 178
179dnl ====================================================================
180dnl Check for systemd
181dnl ====================================================================
182AC_ARG_ENABLE([systemd],
183 AS_HELP_STRING([--enable-systemd], [Use systemd]),
184 [enable_systemd=$enableval],
185 [enable_systemd=auto])
186
187PKG_CHECK_MODULES(SYSTEMD,
188 [libsystemd-daemon],
189 [have_systemd=yes], [have_systemd=no])
190
191AC_MSG_CHECKING([whether to use systemd])
192
193if test x$enable_systemd = xauto ; then
194 if test x$have_systemd = xno ; then
195 enable_systemd=no
196 else
197 enable_systemd=yes
198 fi
199fi
200AC_MSG_RESULT($enable_systemd)
201
202if test x$enable_systemd = xyes; then
203 if test x$have_systemd = xno; then
204 AC_MSG_ERROR([Systemd support explicitly required, but systemd not found])
205 fi
206 AC_DEFINE(HAVE_SYSTEMD, 1, [Define if systemd is used for session tracking])
207fi
208
209AC_SUBST(SYSTEMD_CFLAGS)
210AC_SUBST(SYSTEMD_LIBS)
211
212AM_CONDITIONAL(HAVE_SYSTEMD, [test "$with_systemd" = "yes"], [Using systemd])
213
214AC_ARG_WITH([systemdutildir],
215 AS_HELP_STRING([--with-systemdutildir=DIR], [Directory for systemd utilities]),
216 [],
217 [with_systemdutildir=$($PKG_CONFIG --variable=systemdutildir systemd)])
218AC_SUBST([systemdutildir], [$with_systemdutildir])
219AM_CONDITIONAL(HAVE_SYSTEMDUTILDIR, [test -n "$with_systemdutildir"])
220
221AC_ARG_WITH([systemdsystemunitdir],
222 AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
223 [],
224 [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
225AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
226AM_CONDITIONAL(HAVE_SYSTEMDSYSTEMUNITDIR, [test -n "$with_systemdsystemunitdir"])
227
179dnl --------------------------------------------------------------------------- 228dnl ---------------------------------------------------------------------------
180dnl - Compile time default choice of backend 229dnl - Compile time default choice of backend
181dnl --------------------------------------------------------------------------- 230dnl ---------------------------------------------------------------------------
@@ -210,14 +259,6 @@ fi
210 259
211AM_CONDITIONAL(HAVE_IDEVICE, [test x$have_idevice = xyes]) 260AM_CONDITIONAL(HAVE_IDEVICE, [test x$have_idevice = xyes])
212 261
213# systemd
214AC_ARG_WITH([systemdsystemunitdir],
215 AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
216 [],
217 [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
218AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
219AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir"])
220
221# export to Makefile.am 262# export to Makefile.am
222AM_CONDITIONAL(BACKEND_TYPE_DUMMY, [test x$with_backend = xdummy]) 263AM_CONDITIONAL(BACKEND_TYPE_DUMMY, [test x$with_backend = xdummy])
223AM_CONDITIONAL(BACKEND_TYPE_LINUX, [test x$with_backend = xlinux]) 264AM_CONDITIONAL(BACKEND_TYPE_LINUX, [test x$with_backend = xlinux])
diff --git a/src/Makefile.am b/src/Makefile.am
index 0166861..0bf1165 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -122,7 +122,13 @@ upowerd_LDADD += \
122 linux/libupshared.la \ 122 linux/libupshared.la \
123 $(USB_LIBS) \ 123 $(USB_LIBS) \
124 $(GUDEV_LIBS) \ 124 $(GUDEV_LIBS) \
125 $(IDEVICE_LIBS) 125 $(IDEVICE_LIBS) \
126 $(SYSTEMD_LIBS)
127
128if HAVE_SYSTEMDUTILDIR
129systemsleepdir = $(systemdutildir)/system-sleep
130systemsleep_SCRIPTS = notify-upower.sh
131endif
126 132
127if UP_BUILD_TESTS 133if UP_BUILD_TESTS
128DBUS_LAUNCH=$(shell which dbus-launch) 134DBUS_LAUNCH=$(shell which dbus-launch)
@@ -196,7 +202,7 @@ dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
196$(dbusconf_DATA): $(dbusconf_in_files) Makefile 202$(dbusconf_DATA): $(dbusconf_in_files) Makefile
197 cp $< $@ 203 cp $< $@
198 204
199if HAVE_SYSTEMD 205if HAVE_SYSTEMDSYSTEMUNITDIR
200systemdservicedir = $(systemdsystemunitdir) 206systemdservicedir = $(systemdsystemunitdir)
201systemdservice_in_files = upower.service.in 207systemdservice_in_files = upower.service.in
202systemdservice_DATA = $(systemdservice_in_files:.service.in=.service) 208systemdservice_DATA = $(systemdservice_in_files:.service.in=.service)
@@ -223,6 +229,8 @@ EXTRA_DIST = \
223 org.freedesktop.UPower.KbdBacklight.xml \ 229 org.freedesktop.UPower.KbdBacklight.xml \
224 org.freedesktop.UPower.Wakeups.xml \ 230 org.freedesktop.UPower.Wakeups.xml \
225 up-marshal.list \ 231 up-marshal.list \
232 $(systemsleep_SCRIPTS) \
233 $(systemdservice_in_files) \
226 $(dbusservice_in_files) \ 234 $(dbusservice_in_files) \
227 $(dbusconf_in_files) 235 $(dbusconf_in_files)
228 236
diff --git a/src/dummy/up-backend.c b/src/dummy/up-backend.c
index 834e37d..b860eff 100644
--- a/src/dummy/up-backend.c
+++ b/src/dummy/up-backend.c
@@ -297,3 +297,9 @@ up_backend_get_powersave_command (UpBackend *backend, gboolean powersave)
297{ 297{
298 return "/bin/true"; 298 return "/bin/true";
299} 299}
300
301gboolean
302up_backend_emits_resuming (UpBackend *backend)
303{
304 return FALSE;
305}
diff --git a/src/freebsd/up-backend.c b/src/freebsd/up-backend.c
index e1dd22a..40e8b2b 100644
--- a/src/freebsd/up-backend.c
+++ b/src/freebsd/up-backend.c
@@ -326,6 +326,12 @@ up_backend_get_hibernate_command (UpBackend *backend)
326 return UP_BACKEND_HIBERNATE_COMMAND; 326 return UP_BACKEND_HIBERNATE_COMMAND;
327} 327}
328 328
329gboolean
330up_backend_emits_resuming (UpBackend *backend)
331{
332 return FALSE;
333}
334
329/** 335/**
330 * up_backend_kernel_can_suspend: 336 * up_backend_kernel_can_suspend:
331 **/ 337 **/
diff --git a/src/linux/Makefile.am b/src/linux/Makefile.am
index 520b4cf..2081a66 100644
--- a/src/linux/Makefile.am
+++ b/src/linux/Makefile.am
@@ -12,7 +12,8 @@ INCLUDES = \
12 $(GUDEV_CFLAGS) \ 12 $(GUDEV_CFLAGS) \
13 $(POLKIT_CFLAGS) \ 13 $(POLKIT_CFLAGS) \
14 $(GLIB_CFLAGS) \ 14 $(GLIB_CFLAGS) \
15 $(IDEVICE_CFLAGS) 15 $(IDEVICE_CFLAGS) \
16 $(SYSTEMD_CFLAGS)
16 17
17if BACKEND_TYPE_LINUX 18if BACKEND_TYPE_LINUX
18noinst_LTLIBRARIES = libupshared.la 19noinst_LTLIBRARIES = libupshared.la
diff --git a/src/linux/up-backend.c b/src/linux/up-backend.c
index be01763..ddd4472 100644
--- a/src/linux/up-backend.c
+++ b/src/linux/up-backend.c
@@ -45,6 +45,17 @@
45#include "up-device-idevice.h" 45#include "up-device-idevice.h"
46#endif /* HAVE_IDEVICE */ 46#endif /* HAVE_IDEVICE */
47 47
48#include <dbus/dbus-glib.h>
49#include <dbus/dbus-glib-lowlevel.h>
50
51#ifdef HAVE_SYSTEMD
52#include <systemd/sd-daemon.h>
53
54#define SD_HIBERNATE_COMMAND "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.Hibernate 'true'"
55#define SD_SUSPEND_COMMAND "gdbus call --system --dest org.freedesktop.login1 --object-path /org/freedesktop/login1 --method org.freedesktop.login1.Manager.Suspend 'true'"
56
57#endif
58
48static void up_backend_class_init (UpBackendClass *klass); 59static void up_backend_class_init (UpBackendClass *klass);
49static void up_backend_init (UpBackend *backend); 60static void up_backend_init (UpBackend *backend);
50static void up_backend_finalize (GObject *object); 61static void up_backend_finalize (GObject *object);
@@ -59,11 +70,13 @@ struct UpBackendPrivate
59 UpDeviceList *managed_devices; 70 UpDeviceList *managed_devices;
60 UpDock *dock; 71 UpDock *dock;
61 UpConfig *config; 72 UpConfig *config;
73 DBusConnection *connection;
62}; 74};
63 75
64enum { 76enum {
65 SIGNAL_DEVICE_ADDED, 77 SIGNAL_DEVICE_ADDED,
66 SIGNAL_DEVICE_REMOVED, 78 SIGNAL_DEVICE_REMOVED,
79 SIGNAL_RESUMING,
67 SIGNAL_LAST 80 SIGNAL_LAST
68}; 81};
69 82
@@ -564,6 +577,11 @@ out:
564const gchar * 577const gchar *
565up_backend_get_suspend_command (UpBackend *backend) 578up_backend_get_suspend_command (UpBackend *backend)
566{ 579{
580#ifdef HAVE_SYSTEMD
581 if (sd_booted ())
582 return SD_SUSPEND_COMMAND;
583 else
584#endif
567 return UP_BACKEND_SUSPEND_COMMAND; 585 return UP_BACKEND_SUSPEND_COMMAND;
568} 586}
569 587
@@ -573,9 +591,24 @@ up_backend_get_suspend_command (UpBackend *backend)
573const gchar * 591const gchar *
574up_backend_get_hibernate_command (UpBackend *backend) 592up_backend_get_hibernate_command (UpBackend *backend)
575{ 593{
594#ifdef HAVE_SYSTEMD
595 if (sd_booted ())
596 return SD_HIBERNATE_COMMAND;
597 else
598#endif
576 return UP_BACKEND_HIBERNATE_COMMAND; 599 return UP_BACKEND_HIBERNATE_COMMAND;
577} 600}
578 601
602gboolean
603up_backend_emits_resuming (UpBackend *backend)
604{
605#ifdef HAVE_SYSTEMD
606 return TRUE;
607#else
608 return FALSE;
609#endif
610}
611
579/** 612/**
580 * up_backend_get_powersave_command: 613 * up_backend_get_powersave_command:
581 **/ 614 **/
@@ -609,10 +642,32 @@ up_backend_class_init (UpBackendClass *klass)
609 G_STRUCT_OFFSET (UpBackendClass, device_removed), 642 G_STRUCT_OFFSET (UpBackendClass, device_removed),
610 NULL, NULL, up_marshal_VOID__POINTER_POINTER, 643 NULL, NULL, up_marshal_VOID__POINTER_POINTER,
611 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); 644 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
645 signals [SIGNAL_RESUMING] =
646 g_signal_new ("resuming",
647 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
648 G_STRUCT_OFFSET (UpBackendClass, resuming),
649 NULL, NULL, g_cclosure_marshal_VOID__VOID,
650 G_TYPE_NONE, 0);
612 651
613 g_type_class_add_private (klass, sizeof (UpBackendPrivate)); 652 g_type_class_add_private (klass, sizeof (UpBackendPrivate));
614} 653}
615 654
655static DBusHandlerResult
656message_filter (DBusConnection *connection,
657 DBusMessage *message,
658 void *user_data)
659{
660 UpBackend *backend = user_data;
661
662 if (dbus_message_is_signal (message, "org.freedesktop.UPower", "Resuming")) {
663 g_debug ("received Resuming signal");
664 g_signal_emit (backend, signals[SIGNAL_RESUMING], 0);
665 return DBUS_HANDLER_RESULT_HANDLED;
666 }
667
668 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
669}
670
616/** 671/**
617 * up_backend_init: 672 * up_backend_init:
618 **/ 673 **/
@@ -624,6 +679,15 @@ up_backend_init (UpBackend *backend)
624 backend->priv->daemon = NULL; 679 backend->priv->daemon = NULL;
625 backend->priv->device_list = NULL; 680 backend->priv->device_list = NULL;
626 backend->priv->managed_devices = up_device_list_new (); 681 backend->priv->managed_devices = up_device_list_new ();
682
683#ifdef HAVE_SYSTEMD
684 if (sd_booted ()) {
685 DBusGConnection *bus;
686 bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
687 backend->priv->connection = dbus_g_connection_get_connection (bus);
688 dbus_connection_add_filter (backend->priv->connection, message_filter, backend, NULL);
689 }
690#endif
627} 691}
628 692
629/** 693/**
@@ -648,6 +712,9 @@ up_backend_finalize (GObject *object)
648 712
649 g_object_unref (backend->priv->managed_devices); 713 g_object_unref (backend->priv->managed_devices);
650 714
715 if (backend->priv->connection)
716 dbus_connection_remove_filter (backend->priv->connection, message_filter, backend);
717
651 G_OBJECT_CLASS (up_backend_parent_class)->finalize (object); 718 G_OBJECT_CLASS (up_backend_parent_class)->finalize (object);
652} 719}
653 720
diff --git a/src/notify-upower.sh b/src/notify-upower.sh
new file mode 100755
index 0000000..d88ae5e
--- /dev/null
+++ b/src/notify-upower.sh
@@ -0,0 +1,6 @@
1#!/bin/bash
2[ "$1" = "post" ] && exec /usr/bin/dbus-send \
3 --system --type=signal \
4 --dest=org.freedesktop.UPower \
5 /org/freedesktop/UPower \
6 org.freedesktop.UPower.Resuming
diff --git a/src/openbsd/up-backend.c b/src/openbsd/up-backend.c
index 9d724ba..b25fb44 100644
--- a/src/openbsd/up-backend.c
+++ b/src/openbsd/up-backend.c
@@ -205,6 +205,12 @@ up_backend_get_hibernate_command (UpBackend *backend)
205 return NULL; 205 return NULL;
206} 206}
207 207
208gboolean
209up_backend_emits_resuming (UpBackend *backend)
210{
211 return FALSE;
212}
213
208/** 214/**
209 * up_backend_kernel_can_suspend: 215 * up_backend_kernel_can_suspend:
210 **/ 216 **/
diff --git a/src/up-backend.h b/src/up-backend.h
index 154e2c6..08dac8b 100644
--- a/src/up-backend.h
+++ b/src/up-backend.h
@@ -59,6 +59,7 @@ typedef struct
59 void (* device_removed) (UpBackend *backend, 59 void (* device_removed) (UpBackend *backend,
60 GObject *native, 60 GObject *native,
61 UpDevice *device); 61 UpDevice *device);
62 void (* resuming) (UpBackend *backend);
62} UpBackendClass; 63} UpBackendClass;
63 64
64GType up_backend_get_type (void); 65GType up_backend_get_type (void);
@@ -75,6 +76,7 @@ const gchar *up_backend_get_suspend_command (UpBackend *backend);
75const gchar *up_backend_get_hibernate_command (UpBackend *backend); 76const gchar *up_backend_get_hibernate_command (UpBackend *backend);
76const gchar *up_backend_get_powersave_command (UpBackend *backend, 77const gchar *up_backend_get_powersave_command (UpBackend *backend,
77 gboolean powersave); 78 gboolean powersave);
79gboolean up_backend_emits_resuming (UpBackend *backend);
78 80
79G_END_DECLS 81G_END_DECLS
80 82
diff --git a/src/up-daemon.c b/src/up-daemon.c
index 6165fab..be416ab 100644
--- a/src/up-daemon.c
+++ b/src/up-daemon.c
@@ -380,8 +380,40 @@ typedef struct {
380 UpDaemon *daemon; 380 UpDaemon *daemon;
381 DBusGMethodInvocation *context; 381 DBusGMethodInvocation *context;
382 gchar *command; 382 gchar *command;
383 gulong handler;
383} UpDaemonDeferredSleep; 384} UpDaemonDeferredSleep;
384 385
386static void
387emit_resuming (UpDaemonDeferredSleep *sleep)
388{
389 UpDaemon *daemon = sleep->daemon;
390 UpDaemonPrivate *priv = daemon->priv;
391
392 /* emit signal for session components */
393 g_debug ("emitting resuming");
394 g_signal_emit (daemon, signals[SIGNAL_RESUMING], 0);
395 g_signal_emit (daemon, signals[SIGNAL_NOTIFY_RESUME], 0,
396 priv->sleep_kind);
397
398 /* reset the about-to-sleep logic */
399 g_timer_reset (priv->about_to_sleep_timer);
400 g_timer_stop (priv->about_to_sleep_timer);
401
402 /* actually return from the DBus call now */
403 dbus_g_method_return (sleep->context, NULL);
404
405 /* clear timer */
406 priv->about_to_sleep_id = 0;
407 priv->sent_sleeping_signal = FALSE;
408
409 /* delete temp object */
410 if (sleep->handler)
411 g_signal_handler_disconnect (priv->backend, sleep->handler);
412 g_object_unref (sleep->daemon);
413 g_free (sleep->command);
414 g_free (sleep);
415}
416
385/** 417/**
386 * up_daemon_deferred_sleep_cb: 418 * up_daemon_deferred_sleep_cb:
387 **/ 419 **/
@@ -396,7 +428,13 @@ up_daemon_deferred_sleep_cb (UpDaemonDeferredSleep *sleep)
396 UpDaemon *daemon = sleep->daemon; 428 UpDaemon *daemon = sleep->daemon;
397 UpDaemonPrivate *priv = daemon->priv; 429 UpDaemonPrivate *priv = daemon->priv;
398 430
431 if (up_backend_emits_resuming (priv->backend)) {
432 sleep->handler = g_signal_connect_swapped (priv->backend, "resuming",
433 G_CALLBACK (emit_resuming), sleep);
434 }
435
399 /* run the command */ 436 /* run the command */
437 g_debug ("Running %s", sleep->command);
400 ret = g_spawn_command_line_sync (sleep->command, &stdout, &stderr, NULL, &error_local); 438 ret = g_spawn_command_line_sync (sleep->command, &stdout, &stderr, NULL, &error_local);
401 if (!ret) { 439 if (!ret) {
402 error = g_error_new (UP_DAEMON_ERROR, 440 error = g_error_new (UP_DAEMON_ERROR,
@@ -408,32 +446,13 @@ up_daemon_deferred_sleep_cb (UpDaemonDeferredSleep *sleep)
408 goto out; 446 goto out;
409 } 447 }
410 448
411 /* emit signal for session components */ 449 if (!up_backend_emits_resuming (priv->backend))
412 g_debug ("emitting resuming"); 450 emit_resuming (sleep);
413 g_signal_emit (daemon, signals[SIGNAL_RESUMING], 0);
414 g_signal_emit (daemon, signals[SIGNAL_NOTIFY_RESUME], 0,
415 priv->sleep_kind);
416
417 /* reset the about-to-sleep logic */
418 g_timer_reset (priv->about_to_sleep_timer);
419 g_timer_stop (priv->about_to_sleep_timer);
420
421 /* actually return from the DBus call now */
422 dbus_g_method_return (sleep->context, NULL);
423 451
424out: 452out:
425 /* clear timer */
426 priv->about_to_sleep_id = 0;
427 priv->sent_sleeping_signal = FALSE;
428
429 g_free (stdout); 453 g_free (stdout);
430 g_free (stderr); 454 g_free (stderr);
431 455
432 /* delete temp object */
433 g_object_unref (sleep->daemon);
434 g_free (sleep->command);
435 g_free (sleep);
436
437 return FALSE; 456 return FALSE;
438} 457}
439 458