mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-04-20 10:46:59 +02:00
fixes: https://gitlab.alpinelinux.org/alpine/aports/-/issues/16695 upstream: https://lists.busybox.net/pipermail/busybox/2025-January/091067.html
199 lines
6.9 KiB
Diff
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
|
|
|