systemd-sleep: Set SYSTEMD_SLEEP_ACTION for systemd-sleep hooks.
authorZach Smith <z@zxmth.us>
Fri, 8 Jan 2021 02:06:30 +0000 (18:06 -0800)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 9 Jan 2021 09:11:01 +0000 (18:11 +0900)
When suspend-then-hibernate is called, hooks have no ability to determine which
stage of the request is being handled; they only see 'pre' and 'post' with the
verb 'suspend-then-hibernate'. This change introduces an environment variable
called SYSTEMD_SLEEP_ACTION that contains the name of the action that is
processing: 'suspend', 'hibernate', 'hybrid-sleep', or
'suspend-after-failed-hibernate'.

man/systemd-suspend.service.xml
src/sleep/sleep.c

index e4a6de548f915c70dfaea6895053ee9a4d6831f8..c525a3bda2430bcb2ad7b0d5f0e7cfd60ee7c599 100644 (file)
     <literal>pre</literal>, the second either
     <literal>suspend</literal>, <literal>hibernate</literal>,
     <literal>hybrid-sleep</literal>, or <literal>suspend-then-hibernate</literal>
-    depending on the chosen action.
+    depending on the chosen action. An environment variable called <literal>SYSTEMD_SLEEP_ACTION</literal>
+    will be set and contain the sleep action that is processing. This is primarily helpful for
+    <literal>suspend-then-hibernate</literal> where the value of the variable will be <literal>suspend</literal>, <literal>hibernate</literal>,
+    or <literal>suspend-after-failed-hibernate</literal> in cases where hibernation has failed.
     Immediately after leaving system suspend and/or hibernation the
     same executables are run, but the first argument is now
     <literal>post</literal>. All executables in this directory are
index 39ab55429028703c01b39faf14cc33ac1412f287..90bc90e982600609e74aff6c1774f8a1c5df8bd2 100644 (file)
@@ -169,7 +169,7 @@ static int lock_all_homes(void) {
         return log_debug("Successfully requested locking of all home directories.");
 }
 
-static int execute(char **modes, char **states) {
+static int execute(char **modes, char **states, const char *action) {
         char *arguments[] = {
                 NULL,
                 (char*) "pre",
@@ -211,6 +211,10 @@ static int execute(char **modes, char **states) {
                         return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
         }
 
+        r = setenv("SYSTEMD_SLEEP_ACTION", action, 1);
+        if (r != 0)
+                log_warning_errno(errno, "Error setting SYSTEMD_SLEEP_ACTION=%s: %m", action);
+
         (void) execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL, EXEC_DIR_PARALLEL | EXEC_DIR_IGNORE_ERRORS);
         (void) lock_all_homes();
 
@@ -258,7 +262,7 @@ static int execute_s2h(const SleepConfig *sleep_config) {
         if (r < 0)
                 return log_error_errno(errno, "Error setting hibernate timer: %m");
 
-        r = execute(sleep_config->suspend_modes, sleep_config->suspend_states);
+        r = execute(sleep_config->suspend_modes, sleep_config->suspend_states, "suspend");
         if (r < 0)
                 return r;
 
@@ -274,11 +278,11 @@ static int execute_s2h(const SleepConfig *sleep_config) {
         log_debug("Attempting to hibernate after waking from %s timer",
                   format_timespan(buf, sizeof(buf), sleep_config->hibernate_delay_sec, USEC_PER_SEC));
 
-        r = execute(sleep_config->hibernate_modes, sleep_config->hibernate_states);
+        r = execute(sleep_config->hibernate_modes, sleep_config->hibernate_states, "hibernate");
         if (r < 0) {
                 log_notice_errno(r, "Couldn't hibernate, will try to suspend again: %m");
 
-                r = execute(sleep_config->suspend_modes, sleep_config->suspend_states);
+                r = execute(sleep_config->suspend_modes, sleep_config->suspend_states, "suspend-after-failed-hibernate");
                 if (r < 0)
                         return log_error_errno(r, "Could neither hibernate nor suspend, giving up: %m");
         }
@@ -387,7 +391,7 @@ static int run(int argc, char *argv[]) {
         if (streq(arg_verb, "suspend-then-hibernate"))
                 return execute_s2h(sleep_config);
         else
-                return execute(modes, states);
+                return execute(modes, states, arg_verb);
 }
 
 DEFINE_MAIN_FUNCTION(run);