From 2c1de61023d384fd0a365405925940c3528cb75a Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Thu, 24 Apr 2003 11:41:28 +0000 Subject: [PATCH] There have been many reports of init failing to reboot and/or failing to halt over the years. Well I finally took the time to track this down. It turns out that inside linux/kernel/sys.c the kernel will call machine_halt(); do_exit(0); when halting, or will call machine_power_off(); do_exit(0); during a reboot. Unlike sysv init, we call reboot from within the init process, so if the call to machine_halt() or machine_power_off() returns, the call to do_exit(0) will cause the kernel to panic. Which is a very bad thing to happen. So I just added this little patch to fork and call the reboot syscall from within the forked child process, thereby neatly avoiding the problem. But IMHO, both calls to do_exit(0) within linux/kernel/sys.c are bugs and should be fixed. -Erik --- init/init.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/init/init.c b/init/init.c index be91d6a8f..8adff1cd2 100644 --- a/init/init.c +++ b/init/init.c @@ -46,6 +46,10 @@ #ifdef CONFIG_SYSLOGD # include #endif +#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__) +#include +#endif + #if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__) #define fork vfork @@ -80,13 +84,6 @@ struct serial_struct { }; -#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__) -#include -#define init_reboot(magic) reboot(magic) -#else -#define init_reboot(magic) reboot(0xfee1dead, 672274793, magic) -#endif - #ifndef _PATH_STDPATH #define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" #endif @@ -663,6 +660,23 @@ static void run_actions(int action) } #ifndef DEBUG_INIT +static void init_reboot(unsigned long magic) +{ + pid_t pid; + /* We have to fork here, since the kernel calls do_exit(0) in + * linux/kernel/sys.c, which can cause the machint to panic when + * the init process is killed.... */ + if ((pid = fork()) == 0) { +#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__) + reboot(magic); +#else + reboot(0xfee1dead, 672274793, magic); +#endif + _exit(0); + } + waitpid (pid, NULL, 0); +} + static void shutdown_system(void) { sigset_t block_signals;