summaryrefslogtreecommitdiffstats
path: root/source/a/elogind/ce3616c8864e56bf7efb233242f20197108a9dba.patch
blob: 3fcc03794f61aacd2ff362d22d69f1e6aae72c0f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
From ce3616c8864e56bf7efb233242f20197108a9dba Mon Sep 17 00:00:00 2001
From: Sven Eden <sven@eden-worx.com>
Date: Sun, 21 Apr 2024 17:07:25 +0200
Subject: [PATCH] Send wakeup signal in SIGCHLD handler (#280)

The forked out sleeper process fails to send the wakeup signal, as it
does not share the dbus connection with elogind.

Therefore elogind sends the signal itself once the sleeper has
messaged elogind that it is done via the SIGCHLD signal.

Bug: #280
Signed-off-by: Sven Eden <sven@eden-worx.com>
---
 src/login/elogind.c     | 19 +++++++++++++------
 src/login/logind-dbus.c | 13 +++++--------
 src/login/logind-dbus.h |  4 ++++
 src/login/logind.h      |  3 +++
 4 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/src/login/elogind.c b/src/login/elogind.c
index 11000170a6..e616b8088e 100644
--- a/src/login/elogind.c
+++ b/src/login/elogind.c
@@ -25,6 +25,7 @@
 #include "fd-util.h"
 #include "fileio.h"
 #include "fs-util.h"
+#include "logind-dbus.h"
 #include "mount-setup.h"
 #include "musl_missing.h"
 #include "parse-util.h"
@@ -100,6 +101,11 @@ static int elogind_sigchld_handler(
                         log_debug_elogind( "sleep_fork PID %d waitpid() set status %d", m->sleep_fork_pid, status );
                         if ( WIFEXITED(status) || WIFSIGNALED(status) )
                                 m->sleep_fork_pid = 0;
+                        /* Tell people that they now may take a lock again */
+                        if ( m->sleep_fork_action->sleep_operation != _SLEEP_OPERATION_INVALID ) {
+                                (void) send_prepare_for( m, m->sleep_fork_action, false );
+                                m->sleep_fork_action = NULL; /* All done */
+                        }
                 }
         }
 
@@ -416,12 +422,13 @@ void elogind_manager_free( Manager* m ) {
 int elogind_manager_new( Manager* m ) {
         int r = 0;
 
-        m->cgroups_agent_fd = -1;
-        m->pin_cgroupfs_fd  = -1;
-        m->test_run_flags   = 0;
-        m->do_interrupt     = false;
-        m->sleep_fork_pid   = 0;
-        m->tool_fork_pid    = 0;
+        m->cgroups_agent_fd  = -1;
+        m->pin_cgroupfs_fd   = -1;
+        m->test_run_flags    = 0;
+        m->do_interrupt      = false;
+        m->sleep_fork_pid    = 0;
+        m->tool_fork_pid     = 0;
+        m->sleep_fork_action = NULL;
 
         /* Init poweroff/suspend interruption */
         m->allow_poweroff_interrupts     = false;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 25df8d2cb9..b83dceae9b 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1730,7 +1730,11 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
         return r;
 }
 
+#if 0 /// elogind needs to call this from elogind.c
 static int send_prepare_for(Manager *m, const HandleActionData *a, bool _active) {
+#else
+int send_prepare_for(Manager *m, const HandleActionData *a, bool _active) {
+#endif // 0
         int k = 0, r, active = _active;
 
         assert(m);
@@ -1902,6 +1906,7 @@ static int elogind_execute_shutdown_or_sleep(
          * from the shutdown/sleep routines. Doing this in the main thread would
          * make it impossible to talk to ourselves.
          */
+        m->sleep_fork_action = a; /* Remember this for the SIGCHLD handler */
         forker = strjoina( "e-", handle_action_to_string( a->handle ) );
         t = safe_fork( forker,
                        FORK_LOG|FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO,
@@ -1926,14 +1931,6 @@ static int elogind_execute_shutdown_or_sleep(
                 log_error_errno( r, "%s: shutdown_or_sleep failed: %m", program_invocation_short_name );
         }
 
-        /* As elogind cannot rely on a systemd manager to call all
-         * sleeping processes to wake up, we have to tell them all
-         * by ourselves.
-         * Note: execute_shutdown_or_sleep() does not send the
-         *       signal unless an error occurred. */
-        if ( a->sleep_operation != _SLEEP_OPERATION_INVALID )
-                (void) send_prepare_for( m, a, false );
-
         log_debug_elogind("Exiting from %s", program_invocation_short_name);
 
         _exit( EXIT_SUCCESS );
diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h
index c9d59231d4..aa8bdfeb23 100644
--- a/src/login/logind-dbus.h
+++ b/src/login/logind-dbus.h
@@ -9,6 +9,10 @@
 #include "logind-user.h"
 #include "logind.h"
 
+#if 1 /// elogind needs to call this from elogind.c
+int send_prepare_for(Manager *m, const HandleActionData *a, bool _active);
+#endif // 1
+
 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);
diff --git a/src/login/logind.h b/src/login/logind.h
index 20c73444ed..6eb40ddb6f 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -84,6 +84,9 @@ struct Manager {
         /* elogind might spawn processes to suspend/hibernate, so we need their PIDs to end them properly */
         pid_t sleep_fork_pid; /* for suspend/hibernate fork */
         pid_t tool_fork_pid;  /* for external tool fork */
+
+        /* To wake up sleeping consumers using the right operation, the manager must know what is going on. */
+        const HandleActionData *sleep_fork_action;
 #endif // 0
 
         Seat *seat0;