mirror of
https://github.com/troglobit/finit.git
synced 2026-10-11 17:02:42 +07: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:
+4
-4
@@ -95,7 +95,7 @@ and the service registry.
|
||||
| `SetDebug` | — | — | yes | Toggle Finit's runtime debug flag |
|
||||
| `Signal` | `su` | — | yes | Send signal `u` (1–31) to services matching identity `s` |
|
||||
| `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
|
||||
|
||||
@@ -250,9 +250,9 @@ the following subcommands use the bus first:
|
||||
| `initctl restart` | `Manager1.Restart(svc)` |
|
||||
| `initctl reload` | `Manager1.Reload()` |
|
||||
| `initctl reload S` | `Service1.Reload()` (per-svc) |
|
||||
| `initctl reboot` | `Manager1.Reboot()` |
|
||||
| `initctl halt` | `Manager1.Halt()` |
|
||||
| `initctl poweroff` | `Manager1.Poweroff()` |
|
||||
| `initctl reboot` | `Manager1.Reboot(timeout)` |
|
||||
| `initctl halt` | `Manager1.Halt(timeout)` |
|
||||
| `initctl poweroff` | `Manager1.Poweroff(timeout)` |
|
||||
| `initctl suspend` | `Manager1.Suspend()` |
|
||||
| `initctl debug` | `Manager1.SetDebug()` |
|
||||
| `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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (timeout > 0) {
|
||||
emergency.delay = timeout * 1000;
|
||||
schedule_work(&emergency);
|
||||
}
|
||||
shutdown_bypass(timeout);
|
||||
|
||||
switch (cmd) {
|
||||
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)
|
||||
{
|
||||
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))
|
||||
return link_call_reply_error(call,
|
||||
"org.finit.Error.WrongRunlevel",
|
||||
"Already in shutdown");
|
||||
halt = target;
|
||||
shutdown_bypass((int)timeout);
|
||||
sm_runlevel(level);
|
||||
(void)link_call_reply(call);
|
||||
return 0;
|
||||
@@ -623,11 +630,11 @@ static const link_method_t manager_methods[] = {
|
||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_reload },
|
||||
{ .name = "SetRunlevel", .in_sig = "u", .out_sig = "",
|
||||
.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 },
|
||||
{ .name = "Poweroff", .in_sig = "", .out_sig = "",
|
||||
{ .name = "Poweroff", .in_sig = "u", .out_sig = "",
|
||||
.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 },
|
||||
{ .name = "Suspend", .in_sig = "", .out_sig = "",
|
||||
.flags = LINK_METHOD_PRIVILEGED, .handler = manager_suspend },
|
||||
|
||||
+16
-3
@@ -1067,13 +1067,26 @@ static int do_cmd(int cmd)
|
||||
#ifdef HAVE_DBUS
|
||||
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 */
|
||||
return 0;
|
||||
}
|
||||
return rc; /* 1 = error, -1 = fall back */
|
||||
return -1; /* fall back */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -94,6 +94,29 @@ static void shutdown_wdt_cb(uev_t *w, void *arg, int events)
|
||||
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
|
||||
* D-Bus SetRunlevel method. Refused in runlevel 0/6, deferred via
|
||||
|
||||
Reference in New Issue
Block a user