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
This commit is contained in:
parent
afc01cd485
commit
2c1de61023
28
init/init.c
28
init/init.c
@ -46,6 +46,10 @@
|
|||||||
#ifdef CONFIG_SYSLOGD
|
#ifdef CONFIG_SYSLOGD
|
||||||
# include <sys/syslog.h>
|
# include <sys/syslog.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__)
|
||||||
|
#include <sys/reboot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
|
#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
|
||||||
#define fork vfork
|
#define fork vfork
|
||||||
@ -80,13 +84,6 @@ struct serial_struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if (__GNU_LIBRARY__ > 5) || defined(__dietlibc__)
|
|
||||||
#include <sys/reboot.h>
|
|
||||||
#define init_reboot(magic) reboot(magic)
|
|
||||||
#else
|
|
||||||
#define init_reboot(magic) reboot(0xfee1dead, 672274793, magic)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _PATH_STDPATH
|
#ifndef _PATH_STDPATH
|
||||||
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
|
#define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin"
|
||||||
#endif
|
#endif
|
||||||
@ -663,6 +660,23 @@ static void run_actions(int action)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DEBUG_INIT
|
#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)
|
static void shutdown_system(void)
|
||||||
{
|
{
|
||||||
sigset_t block_signals;
|
sigset_t block_signals;
|
||||||
|
Loading…
Reference in New Issue
Block a user