mirror of
https://github.com/troglobit/finit.git
synced 2026-11-10 16:31:21 +00:00
dbus: honor the shutdown timeout in the reboot family
initctl -t N reboot arms an emergency bypass timer over the legacy socket, but the bus methods took no argument, so the timeout was silently dropped whenever D-Bus was up. Reboot, Halt, and Poweroff now take a timeout in seconds, 0 for none, armed via the same shutdown_bypass() the legacy path uses. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
6 files changed
+55
-24
No files matched your search
+4
-4
@@ -95,7 +95,7 @@ and the service registry.
|
|||||||
| `SetDebug` | — | — | yes | Toggle Finit's runtime debug flag |
|
| `SetDebug` | — | — | yes | Toggle Finit's runtime debug flag |
|
||||||
| `Signal` | `su` | — | yes | Send signal `u` (1–31) to services matching identity `s` |
|
| `Signal` | `su` | — | yes | Send signal `u` (1–31) to services matching identity `s` |
|
||||||
| `Suspend` | — | — | yes | `sync()` + suspend-to-RAM |
|
| `Suspend` | — | — | yes | `sync()` + suspend-to-RAM |
|
||||||
| `Reboot`, `Halt`, `Poweroff` | — | — | yes | Trigger the corresponding shutdown sequence |
|
| `Reboot`, `Halt`, `Poweroff` | `u` | — | yes | Trigger the corresponding shutdown sequence; the argument arms the emergency fallback timer (seconds, 0 = none) |
|
||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
|
|
||||||
@@ -250,9 +250,9 @@ the following subcommands use the bus first:
|
|||||||
| `initctl restart` | `Manager1.Restart(svc)` |
|
| `initctl restart` | `Manager1.Restart(svc)` |
|
||||||
| `initctl reload` | `Manager1.Reload()` |
|
| `initctl reload` | `Manager1.Reload()` |
|
||||||
| `initctl reload S` | `Service1.Reload()` (per-svc) |
|
| `initctl reload S` | `Service1.Reload()` (per-svc) |
|
||||||
| `initctl reboot` | `Manager1.Reboot()` |
|
| `initctl reboot` | `Manager1.Reboot(timeout)` |
|
||||||
| `initctl halt` | `Manager1.Halt()` |
|
| `initctl halt` | `Manager1.Halt(timeout)` |
|
||||||
| `initctl poweroff` | `Manager1.Poweroff()` |
|
| `initctl poweroff` | `Manager1.Poweroff(timeout)` |
|
||||||
| `initctl suspend` | `Manager1.Suspend()` |
|
| `initctl suspend` | `Manager1.Suspend()` |
|
||||||
| `initctl debug` | `Manager1.SetDebug()` |
|
| `initctl debug` | `Manager1.SetDebug()` |
|
||||||
| `initctl signal` | `Manager1.Signal(svc, signo)` |
|
| `initctl signal` | `Manager1.Signal(svc, signo)` |
|
||||||
|
|||||||
@@ -222,16 +222,6 @@ static svc_t *do_find_byc(char *buf, size_t len)
|
|||||||
return svc_find_by_cond(input);
|
return svc_find_by_cond(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bypass_shutdown(void *);
|
|
||||||
struct wq emergency = { .cb = bypass_shutdown };
|
|
||||||
|
|
||||||
static void bypass_shutdown(void *unused)
|
|
||||||
{
|
|
||||||
(void)unused;
|
|
||||||
|
|
||||||
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
|
||||||
do_shutdown(halt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -298,10 +288,7 @@ static int do_reboot(int cmd, int timeout, char *buf, size_t len)
|
|||||||
return 255;
|
return 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout > 0) {
|
shutdown_bypass(timeout);
|
||||||
emergency.delay = timeout * 1000;
|
|
||||||
schedule_work(&emergency);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case INIT_CMD_REBOOT:
|
case INIT_CMD_REBOOT:
|
||||||
|
|||||||
+10
-3
@@ -462,11 +462,18 @@ static int manager_set_runlevel(link_call_t *call, void *userdata)
|
|||||||
|
|
||||||
static int dbus_shutdown(link_call_t *call, shutop_t target, int level)
|
static int dbus_shutdown(link_call_t *call, shutop_t target, int level)
|
||||||
{
|
{
|
||||||
|
uint32_t timeout;
|
||||||
|
|
||||||
|
if (link_call_read_u32(call, &timeout) < 0)
|
||||||
|
return link_call_reply_error(call,
|
||||||
|
"org.freedesktop.DBus.Error.InvalidArgs",
|
||||||
|
"expected (u)");
|
||||||
if (IS_RESERVED_RUNLEVEL(runlevel))
|
if (IS_RESERVED_RUNLEVEL(runlevel))
|
||||||
return link_call_reply_error(call,
|
return link_call_reply_error(call,
|
||||||
"org.finit.Error.WrongRunlevel",
|
"org.finit.Error.WrongRunlevel",
|
||||||
"Already in shutdown");
|
"Already in shutdown");
|
||||||
halt = target;
|
halt = target;
|
||||||
|
shutdown_bypass((int)timeout);
|
||||||
sm_runlevel(level);
|
sm_runlevel(level);
|
||||||
(void)link_call_reply(call);
|
(void)link_call_reply(call);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -623,11 +630,11 @@ static const link_method_t manager_methods[] = {
|
|||||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_reload },
|
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_reload },
|
||||||
{ .name = "SetRunlevel", .in_sig = "u", .out_sig = "",
|
{ .name = "SetRunlevel", .in_sig = "u", .out_sig = "",
|
||||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_set_runlevel },
|
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_set_runlevel },
|
||||||
{ .name = "Reboot", .in_sig = "", .out_sig = "",
|
{ .name = "Reboot", .in_sig = "u", .out_sig = "",
|
||||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_reboot },
|
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_reboot },
|
||||||
{ .name = "Poweroff", .in_sig = "", .out_sig = "",
|
{ .name = "Poweroff", .in_sig = "u", .out_sig = "",
|
||||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_poweroff },
|
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_poweroff },
|
||||||
{ .name = "Halt", .in_sig = "", .out_sig = "",
|
{ .name = "Halt", .in_sig = "u", .out_sig = "",
|
||||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_halt },
|
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_halt },
|
||||||
{ .name = "Suspend", .in_sig = "", .out_sig = "",
|
{ .name = "Suspend", .in_sig = "", .out_sig = "",
|
||||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_suspend },
|
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_suspend },
|
||||||
|
|||||||
+16
-3
@@ -1067,13 +1067,26 @@ static int do_cmd(int cmd)
|
|||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
static int do_reboot_dbus(const char *method)
|
static int do_reboot_dbus(const char *method)
|
||||||
{
|
{
|
||||||
int rc = try_dbus_manager(method, "", NULL);
|
link_client_t *c;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (rc == 0) {
|
c = link_client_open(FINIT_BUS_SOCKET);
|
||||||
|
if (!c)
|
||||||
|
return -1; /* fall back to legacy transport */
|
||||||
|
|
||||||
|
/* Timeout in seconds arms the emergency shutdown bypass, 0 = none */
|
||||||
|
rc = link_client_call_v(c, "/org/finit/manager",
|
||||||
|
"org.finit.Manager1", method,
|
||||||
|
"u", (uint32_t)timeout);
|
||||||
|
if (rc == LINK_CALL_ERROR)
|
||||||
|
map_dbus_err(c, method, NULL); /* exits */
|
||||||
|
link_client_close(c);
|
||||||
|
|
||||||
|
if (rc == LINK_CALL_OK) {
|
||||||
sleep(5); /* match legacy: wait for finit to shut down */
|
sleep(5); /* match legacy: wait for finit to shut down */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return rc; /* 1 = error, -1 = fall back */
|
return -1; /* fall back */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,29 @@ static void shutdown_wdt_cb(uev_t *w, void *arg, int events)
|
|||||||
do_shutdown(halt);
|
do_shutdown(halt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emergency shutdown bypass, same job as the shutdown watchdog above
|
||||||
|
* but armed by the user: `initctl -t SEC reboot`, on either transport.
|
||||||
|
*/
|
||||||
|
static void bypass_shutdown(void *unused)
|
||||||
|
{
|
||||||
|
(void)unused;
|
||||||
|
|
||||||
|
cprintf("TIMEOUT TIMEOUT SHUTTING DOWN NOW!!\n");
|
||||||
|
do_shutdown(halt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wq emergency = { .cb = bypass_shutdown };
|
||||||
|
|
||||||
|
void shutdown_bypass(int timeout)
|
||||||
|
{
|
||||||
|
if (timeout <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
emergency.delay = timeout * 1000;
|
||||||
|
schedule_work(&emergency);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* User-requested runlevel change, shared by the legacy API and the
|
* User-requested runlevel change, shared by the legacy API and the
|
||||||
* D-Bus SetRunlevel method. Refused in runlevel 0/6, deferred via
|
* D-Bus SetRunlevel method. Refused in runlevel 0/6, deferred via
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ int sm_in_reload (void);
|
|||||||
void sm_reload (void);
|
void sm_reload (void);
|
||||||
void sm_runlevel (int newlevel);
|
void sm_runlevel (int newlevel);
|
||||||
void sm_request_runlevel(int lvl);
|
void sm_request_runlevel(int lvl);
|
||||||
|
void shutdown_bypass(int timeout);
|
||||||
|
|
||||||
#endif /* FINIT_SM_H_ */
|
#endif /* FINIT_SM_H_ */
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user