aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-04-24 11:41:28 +0000
committerEric Andersen <andersen@codepoet.org>2003-04-24 11:41:28 +0000
commit2c1de61023d384fd0a365405925940c3528cb75a (patch)
tree5839e97767864319de033cec3448767e0e43d016
parentafc01cd48544d4e0e7575a8518e575dd499e297c (diff)
downloadbusybox-w32-2c1de61023d384fd0a365405925940c3528cb75a.tar.gz
busybox-w32-2c1de61023d384fd0a365405925940c3528cb75a.tar.bz2
busybox-w32-2c1de61023d384fd0a365405925940c3528cb75a.zip
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
-rw-r--r--init/init.c28
1 files 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 @@
46#ifdef CONFIG_SYSLOGD 46#ifdef CONFIG_SYSLOGD
47# include <sys/syslog.h> 47# include <sys/syslog.h>
48#endif 48#endif
49#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__)
50#include <sys/reboot.h>
51#endif
52
49 53
50#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__) 54#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
51#define fork vfork 55#define fork vfork
@@ -80,13 +84,6 @@ struct serial_struct {
80}; 84};
81 85
82 86
83#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__)
84#include <sys/reboot.h>
85#define init_reboot(magic) reboot(magic)
86#else
87#define init_reboot(magic) reboot(0xfee1dead, 672274793, magic)
88#endif
89
90#ifndef _PATH_STDPATH 87#ifndef _PATH_STDPATH
91#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" 88#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
92#endif 89#endif
@@ -663,6 +660,23 @@ static void run_actions(int action)
663} 660}
664 661
665#ifndef DEBUG_INIT 662#ifndef DEBUG_INIT
663static void init_reboot(unsigned long magic)
664{
665 pid_t pid;
666 /* We have to fork here, since the kernel calls do_exit(0) in
667 * linux/kernel/sys.c, which can cause the machint to panic when
668 * the init process is killed.... */
669 if ((pid = fork()) == 0) {
670#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__)
671 reboot(magic);
672#else
673 reboot(0xfee1dead, 672274793, magic);
674#endif
675 _exit(0);
676 }
677 waitpid (pid, NULL, 0);
678}
679
666static void shutdown_system(void) 680static void shutdown_system(void)
667{ 681{
668 sigset_t block_signals; 682 sigset_t block_signals;