Change to runlevel 0/6 on reboot/halt/poweroff

This patch fixes a long-standing issue with how Finit handles shutdown,
reboot and poweroff -- and even runlevel changes to runlevel 0 and 6.

Prior to this patch sig.c:do_shutdown() was called immediately on any
of the above events, disregarding any services that a user might have
wanted to run as part of the shutdown/reboot.

With this change the handling is unified in all frontends to instead
do a runlevel change followed by the do_shutdown() action.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2016-09-18 11:50:07 +02:00
1 parent 2c1e9877f9
commit f7d6d269c7
6 files changed
+49 -50

No files matched your search

-2
View File
@@ -20,8 +20,6 @@ General
* Add halt/poweroff/shutdown symlinks to finit and convert reboot, but * Add halt/poweroff/shutdown symlinks to finit and convert reboot, but
only install symlinks if these tools don't already exist. only install symlinks if these tools don't already exist.
* Step state machine at shutdown instead of killing, same as shifting to
runlevel 0 or 6, then call external (newly installed?) tool to reboot.
* Add support for timed shutdown in Finit, including cancelled shutdown. * Add support for timed shutdown in Finit, including cancelled shutdown.
* SysV init and systemd use SIGUSR1 to restart their FIFO/D-Bus. Add * SysV init and systemd use SIGUSR1 to restart their FIFO/D-Bus. Add
API restart to SIGHUP callback for the same functionality in Finit. API restart to SIGHUP callback for the same functionality in Finit.
+14 -16
View File
@@ -217,9 +217,14 @@ static int do_handle_emit(char *buf, size_t len)
return result; return result;
} }
/*
* In contrast to the SysV compat handling in plugins/initctl.c, when
* `initctl runlevel 0` is issued we default to POWERDOWN the system
* instead of just halting.
*/
static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events))
{ {
int sd; int sd, lvl;
struct init_request rq; struct init_request rq;
sd = accept(w->fd, NULL, NULL); sd = accept(w->fd, NULL, NULL);
@@ -255,26 +260,19 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events))
switch (rq.cmd) { switch (rq.cmd) {
case INIT_CMD_RUNLVL: case INIT_CMD_RUNLVL:
switch (rq.runlevel) { switch (rq.runlevel) {
case '0':
_d("Halting system (SIGUSR2)");
do_shutdown(SHUT_OFF);
break;
case 's': case 's':
case 'S': case 'S':
_d("Cannot enter bootstrap after boot ..."); rq.runlevel = '1'; /* Single user mode */
rq.runlevel = '1';
/* Fall through to regular processing */ /* Fall through to regular processing */
case '1'...'5': case '0'...'9':
case '7'...'9':
_d("Setting new runlevel %c", rq.runlevel); _d("Setting new runlevel %c", rq.runlevel);
service_runlevel(rq.runlevel - '0'); lvl = rq.runlevel - '0';
break; if (lvl == 0)
halt = SHUT_OFF;
case '6': if (lvl == 6)
_d("Rebooting system (SIGUSR1)"); halt = SHUT_REBOOT;
do_shutdown(SHUT_REBOOT); service_runlevel(lvl);
break; break;
default: default:
+10 -21
View File
@@ -39,13 +39,6 @@
#include "../sig.h" #include "../sig.h"
#include "../service.h" #include "../service.h"
/*
* Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT",
* "=POWERDOWN", or "" to cancel shutdown, before requesting change to
* runlevel 6 over the /dev/initctl FIFO.
*/
shutop_t halt = SHUT_DEFAULT;
static void parse(void *arg, int fd, int events); static void parse(void *arg, int fd, int events);
static void setup(void *arg); static void setup(void *arg);
@@ -99,11 +92,15 @@ static void set_env(char *data)
} }
/* /*
* Standard reboot/shutdown utilities talk to init using /dev/initctl. * Standard reboot/shutdown utilities talk to init using /run/initctl.
* We should check if the fifo was recreated and reopen it. * We should check if the fifo was recreated and reopen it.
*
* For SysV compatibility the default is to halt the system when issuing
* `init 0`, unless INIT_HALT=POWERDOWN, as performed by the SysV utils.
*/ */
static void parse(void *UNUSED(arg), int fd, int UNUSED(events)) static void parse(void *UNUSED(arg), int fd, int UNUSED(events))
{ {
int lvl;
struct init_request rq; struct init_request rq;
while (1) { while (1) {
@@ -132,25 +129,17 @@ static void parse(void *UNUSED(arg), int fd, int UNUSED(events))
switch (rq.cmd) { switch (rq.cmd) {
case INIT_CMD_RUNLVL: case INIT_CMD_RUNLVL:
switch (rq.runlevel) { switch (rq.runlevel) {
case '0':
_d("Halting system (SIGUSR1 or SIGUSR2)");
do_shutdown(halt);
break;
case 's': case 's':
case 'S': case 'S':
rq.runlevel = '1'; rq.runlevel = '1';
/* Fall through to regular processing */ /* Fall through to regular processing */
case '1'...'5': case '0'...'9':
case '7'...'9':
_d("Setting new runlevel %c", rq.runlevel); _d("Setting new runlevel %c", rq.runlevel);
service_runlevel(rq.runlevel - '0'); lvl = rq.runlevel - '0';
break; if (lvl == 6)
halt = SHUT_REBOOT;
case '6': service_runlevel(lvl);
_d("Rebooting system (SIGTERM)");
do_shutdown(SHUT_REBOOT);
break; break;
default: default:
+15 -4
View File
@@ -80,6 +80,13 @@
#include "service.h" #include "service.h"
#include "utmp-api.h" #include "utmp-api.h"
/*
* Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT",
* "=POWERDOWN", or "" to cancel shutdown, before requesting change to
* runlevel 6 over the /dev/initctl FIFO. See plugins/initctl.c
*/
shutop_t halt = SHUT_DEFAULT;
static int stopped = 0; static int stopped = 0;
static uev_t sigterm_watcher, sigusr1_watcher, sigusr2_watcher; static uev_t sigterm_watcher, sigusr1_watcher, sigusr2_watcher;
static uev_t sighup_watcher, sigint_watcher, sigpwr_watcher; static uev_t sighup_watcher, sigint_watcher, sigpwr_watcher;
@@ -184,7 +191,8 @@ static void sighup_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
*/ */
static void sigint_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) static void sigint_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
do_shutdown(SHUT_REBOOT); halt = SHUT_REBOOT;
service_runlevel(6);
} }
/* /*
@@ -192,7 +200,8 @@ static void sigint_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
*/ */
static void sigusr1_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) static void sigusr1_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
do_shutdown(SHUT_HALT); halt = SHUT_HALT;
service_runlevel(0);
} }
/* /*
@@ -200,7 +209,8 @@ static void sigusr1_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
*/ */
static void sigusr2_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) static void sigusr2_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
do_shutdown(SHUT_OFF); halt = SHUT_OFF;
service_runlevel(0);
} }
/* /*
@@ -208,7 +218,8 @@ static void sigusr2_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
*/ */
static void sigterm_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events)) static void sigterm_cb(uev_t *UNUSED(w), void *UNUSED(arg), int UNUSED(events))
{ {
do_shutdown(SHUT_REBOOT); halt = SHUT_REBOOT;
service_runlevel(6);
} }
/* /*
+2
View File
@@ -66,6 +66,8 @@ typedef enum {
SHUT_REBOOT SHUT_REBOOT
} shutop_t; } shutop_t;
extern shutop_t halt;
void do_shutdown (shutop_t op); void do_shutdown (shutop_t op);
int sig_stopped (void); int sig_stopped (void);
void sig_init (void); void sig_init (void);
+8 -7
View File
@@ -160,13 +160,14 @@ restart:
/* Cleanup stale services */ /* Cleanup stale services */
svc_clean_dynamic(service_unregister); svc_clean_dynamic(service_unregister);
if (0 == runlevel) { /*
do_shutdown(SHUT_OFF); * "I've seen things you people wouldn't believe. Attack ships on fire off
sm->state = SM_RUNNING_STATE; * the shoulder of Orion. I watched C-beams glitter in the dark near the
break; * Tannhäuser Gate. All those .. moments .. will be lost in time, like
} * tears ... in ... rain."
if (6 == runlevel) { */
do_shutdown(SHUT_REBOOT); if (runlevel == 0 || runlevel == 6) {
do_shutdown(halt);
sm->state = SM_RUNNING_STATE; sm->state = SM_RUNNING_STATE;
break; break;
} }