aports/main/busybox/0001-init-add-support-for-separate-reboot-action.patch

199 lines
6.9 KiB
Diff

From 0e797502f58df6f7bc06202de5b30c3a2df52437 Mon Sep 17 00:00:00 2001
From: Natanael Copa <ncopa@alpinelinux.org>
Date: Fri, 17 Jan 2025 09:12:08 +0100
Subject: [PATCH] init: add support for separate reboot action
Make it possible for service managers to differentiate a reboot vs
shutdown event.
Allows user to configure what should happen on SIGTERM (sent by
/sbin/reboot).
For example:
::shutdown:/sbin/openrc shutdown
If no shutdown action is specified in inittab, fall back to shutdown
action, so we don't break backwards compatibility.
downstream-issue: https://gitlab.alpinelinux.org/alpine/aports/-/issues/16695
function old new delta
run 256 686 +430
check_delayed_sigs 362 447 +85
run_actions 126 141 +15
static.actions 64 71 +7
parse_inittab 477 473 -4
reset_sighandlers_and_unblock_sigs 22 - -22
open_stdio_to_tty 85 - -85
run_shutdown_and_kill_processes 111 - -111
init_exec 396 - -396
------------------------------------------------------------------------------
(add/remove: 0/4 grow/shrink: 4/1 up/down: 537/-618) Total: -81 bytes
text data bss dec hex filename
824050 14108 2008 840166 cd1e6 busybox_old
823969 14108 2008 840085 cd195 busybox_unstripped
Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
---
init/init.c | 52 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 17 deletions(-)
diff --git a/init/init.c b/init/init.c
index 2ee1e4cde..47809a1e8 100644
--- a/init/init.c
+++ b/init/init.c
@@ -184,17 +184,27 @@
/*
* Start these before killing all processes in preparation for
* running RESTART actions or doing low-level halt/reboot/poweroff
- * (initiated by SIGUSR1/SIGTERM/SIGUSR2).
+ * (initiated by SIGUSR1/SIGUSR2).
+ * Will also run as fallback if no REBOOT actions were execute on
+ * SIGTERM.
* Wait for completion before proceeding.
*/
#define SHUTDOWN 0x40
+/*
+ * Start these before killing all processes in preparation for
+ * doing low-level reboot (initiated by SIGTERM).
+ * If no reboot actions were executed, it will execute the SHUTDOWN
+ * actions as fallback.
+ * Wait for completion before proceeding.
+ */
+#define REBOOT 0x80
/*
* exec() on SIGQUIT. SHUTDOWN actions are started and waited for,
* then all processes are killed, then init exec's 1st RESTART action,
* replacing itself by it. If no RESTART action specified,
* SIGQUIT has no effect.
*/
-#define RESTART 0x80
+#define RESTART 0x100
/* A linked list of init_actions, to be read from inittab */
struct init_action {
@@ -591,17 +601,19 @@ static void waitfor(pid_t pid)
}
/* Run all commands of a particular type */
-static void run_actions(int action_type)
+/* return 0 if no actions were run */
+static int run_actions(int action_type)
{
struct init_action *a;
+ pid_t pid = 0;
for (a = G.init_action_list; a; a = a->next) {
if (!(a->action_type & action_type))
continue;
- if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
- pid_t pid = run(a);
- if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
+ if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN | REBOOT)) {
+ pid = run(a);
+ if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | REBOOT))
waitfor(pid);
}
if (a->action_type & (RESPAWN | ASKFIRST)) {
@@ -612,9 +624,10 @@ static void run_actions(int action_type)
a->pid = run(a);
}
}
+ return pid != 0;
}
-static void new_init_action(uint8_t action_type, const char *command, const char *cons)
+static void new_init_action(uint32_t action_type, const char *command, const char *cons)
{
struct init_action *a, **nextp;
@@ -705,7 +718,7 @@ static void parse_inittab(void)
/* order must correspond to SYSINIT..RESTART constants */
static const char actions[] ALIGN1 =
"sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
- "ctrlaltdel\0""shutdown\0""restart\0";
+ "ctrlaltdel\0""shutdown\0""reboot\0""restart\0";
int action;
char *tty = token[0];
@@ -755,12 +768,14 @@ static void pause_and_low_level_reboot(unsigned magic)
_exit_SUCCESS();
}
-static void run_shutdown_and_kill_processes(void)
+static void run_shutdown_and_kill_processes(int sig)
{
/* Run everything to be run at "shutdown". This is done _prior_
* to killing everything, in case people wish to use scripts to
* shut things down gracefully... */
- run_actions(SHUTDOWN);
+ if ((sig != SIGTERM) || (run_actions(REBOOT) == 0)) {
+ (void)run_actions(SHUTDOWN);
+ }
message(L_CONSOLE | L_LOG, "The system is going down NOW!");
@@ -821,7 +836,7 @@ static void halt_reboot_pwoff(int sig)
*/
reset_sighandlers_and_unblock_sigs();
- run_shutdown_and_kill_processes();
+ run_shutdown_and_kill_processes(sig);
m = "halt";
rb = RB_HALT_SYSTEM;
@@ -854,7 +869,7 @@ static void exec_restart_action(void)
reset_sighandlers_and_unblock_sigs();
- run_shutdown_and_kill_processes();
+ run_shutdown_and_kill_processes(SIGQUIT);
#ifdef RB_ENABLE_CAD
/* Allow Ctrl-Alt-Del to reboot the system.
@@ -986,7 +1001,7 @@ static void check_delayed_sigs(struct timespec *ts)
reload_inittab();
#endif
if (sig == SIGINT)
- run_actions(CTRLALTDEL);
+ (void)run_actions(CTRLALTDEL);
if (sig == SIGQUIT) {
exec_restart_action();
/* returns only if no restart action defined */
@@ -1179,18 +1194,18 @@ int init_main(int argc UNUSED_PARAM, char **argv)
/* Now run everything that needs to be run */
/* First run the sysinit command */
- run_actions(SYSINIT);
+ (void)run_actions(SYSINIT);
check_delayed_sigs(&G.zero_ts);
/* Next run anything that wants to block */
- run_actions(WAIT);
+ (void)run_actions(WAIT);
check_delayed_sigs(&G.zero_ts);
/* Next run anything to be run only once */
- run_actions(ONCE);
+ (void)run_actions(ONCE);
/* Now run the looping stuff for the rest of forever */
while (1) {
/* (Re)run the respawn/askfirst stuff */
- run_actions(RESPAWN | ASKFIRST);
+ (void)run_actions(RESPAWN | ASKFIRST);
/* Wait for any signal (typically it's SIGCHLD) */
check_delayed_sigs(NULL); /* NULL timespec makes it wait */
@@ -1355,5 +1370,8 @@ int init_main(int argc UNUSED_PARAM, char **argv)
//usage: " \n"
//usage: " # Stuff to do before rebooting\n"
//usage: " ::ctrlaltdel:/sbin/reboot\n"
+//usage: " ::reboot:/bin/umount -a -r\n"
+//usage: " ::reboot:/sbin/swapoff -a\n"
+//usage: " # Stuff to do before poweroff (also fallback when no reboot actions specified)\n"
//usage: " ::shutdown:/bin/umount -a -r\n"
//usage: " ::shutdown:/sbin/swapoff -a\n"
--
2.48.1