[PATCH] init.c, halt command not working
Harald Kuethe
harald-tuxbox at arcor.de
Fri Apr 4 20:40:02 UTC 2008
----- Original Message -----
From: "Denys Vlasenko" <vda.linux at googlemail.com>
To: "Harald Kuethe" <harald-tuxbox at arcor.de>
Cc: <busybox at busybox.net>
Sent: Friday, April 04, 2008 3:06 AM
Subject: Re: [PATCH] init.c, halt command not working
> On Thursday 03 April 2008 23:33, Harald Kuethe wrote:
>> > ----- Original Message -----
>> > From: "Denys Vlasenko" <vda.linux at googlemail.com>
>> > To: "Harald Kuethe" <harald-tuxbox at arcor.de>
>> > Cc: <busybox at busybox.net>
>> > Sent: Wednesday, April 02, 2008 11:41 PM
>> > Subject: Re: [PATCH] init.c, halt command not working
>>
>> ...
>>
>> > kill() returns 0 (success), so the system thinks that SIGTERM is delivered.
>> > But init does not print your debug message. Very strange.
>> > killall did the very same thing: "kill(1, SIGTERM)" and it worked...
>>
>> > Please try attached idagnostic patch.
>> > It will spam your console if it will detect that init
>> > has TERM blocked or set to unexpected handler.
>>
>> > Try to "kill 1" and "kill -USR1 1" and report what init says.
>> > --
>> > vda
>>
>> This patch adds no additional output :-/
>> I put some more debugging output into the init_main function to find out where it hangs.
>> It showed that init_main does not return from the run_actions(ASKFIRST); call,
>> this explains that the additional diagnostics didn't come up.
>>
>> Following lines are copied from our inittab:
>> ...
>> ::askfirst:-/bin/sh
>> vc/2::askfirst:-/bin/sh
>> vc/3::askfirst:-/bin/sh
>> ...
>>
>> It looks as if the init process is replaced by the shell without finishing generating the virtual consoles and waiting in the while loop
>> because there are only 2 init processes here (there were some more (one for each vc) with the fork() instead of the vfork())
>
> Huh. Soulds almost as if vfork() never returns in parent... ?!
> Can you check?
>
> static pid_t run(const struct init_action *a)
> {
> pid_t pid;
> sigset_t nmask, omask;
>
> /* Block sigchild while forking (why?) */
> sigemptyset(&nmask);
> sigaddset(&nmask, SIGCHLD);
> sigprocmask(SIG_BLOCK, &nmask, &omask);
> pid = vfork();
> +bb_error_msg("vfork returned %d", (int)pid);
> sigprocmask(SIG_SETMASK, &omask, NULL);
> ...
>
>
> and here:
>
>
> static void run_actions(int action_type)
> {
> struct init_action *a, *tmp;
>
> for (a = init_action_list; a; a = tmp) {
> tmp = a->next;
> if (a->action_type == action_type) {
> // Pointless: run() will error out if open of device fails.
> ///* a->terminal of "" means "init's console" */
> //if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
> // //message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);
> // delete_init_action(a);
> //} else
> if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
> +bb_error_msg("before waitfor(run(a))");
> waitfor(run(a));
> +bb_error_msg("after waitfor(run(a))");
> delete_init_action(a);
> } else if (a->action_type & ONCE) {
> +bb_error_msg("before run(a)");
> run(a);
> +bb_error_msg("after run(a)");
> delete_init_action(a);
> } else if (a->action_type & (RESPAWN | ASKFIRST)) {
> /* Only run stuff with pid==0. If they have
> * a pid, that means it is still running */
> if (a->pid == 0) {
> +bb_error_msg("before a->pid = run(a)");
> a->pid = run(a);
> +bb_error_msg("after a->pid = run(a)");
> }
> }
>
>
> and here:
>
> static void waitfor(pid_t pid)
> {
> /* waitfor(run(x)): protect against failed fork inside run() */
> if (pid <= 0)
> return;
> +bb_error_msg("waiting for %d", (int)pid);
> /* Wait for any child (prevent zombies from exiting orphaned processes)
> * but exit the loop only when specified one has exited. */
> while (wait(NULL) != pid)
> continue;
> }
>
>
> --
> vda
Ok, here's the result:
The first part is with a vfork() call in static pid_t run(const struct init_action *a)
the second part uses fork()
Freeing unused kernel memory: 68k init
*Start init_main
init: waiting for 10
*console_init
init started
init started: BusyBox v1.10.0 (2008-04-01 22:01:03 CEST)
*single?
*run_actions
init: before waitfor(run(a))
init: run vfork returned 0
init: run vfork returned 11
*call bb_signals
init: waiting for 11
...
init: after waitfor(run(a))
*signals
*RESPAWN
*ASKFIRST
init: before a->pid = run(a)
init: run vfork returned 0
Please press Enter to activate this console.
init: run vfork returned 80
*call bb_signals
init: after a->pid = run(a)
init: before a->pid = run(a)
init: run vfork returned 0
BusyBox v1.10.0 (2008-04-01 22:01:03 CEST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
/ #
/ #
/ # ps -ef
PID USER VSZ STAT COMMAND
1 root 0 D init
2 root 0 S [keventd]
3 root 0 S [ksoftirqd_CPU0]
4 root 0 S [kswapd]
5 root 0 S [bdflush]
6 root 0 S [kupdated]
7 root 0 S [cifsoplockd]
8 root 0 S [mtdblockd]
9 root 0 S [rpciod]
21 root 0 S inetd
56 root 0 S [avia_av_wdt]
60 root 0 S [avia_gt_wdt]
80 root 0 S -/bin/sh
81 root 0 S init
83 root 0 R ps -ef
/ #
/ # kill 1
/ # kill -SIGUSR1 1
/ # halt
/ # killall init
*HK: halt_reboot_pwoff
init: before waitfor(run(a))
init: run vfork returned 0
init: run vfork returned 86
*call bb_signals
init: waiting for 86
init: after waitfor(run(a))
The system is going down NOW!
init: waiting for 95
Sending SIGTERM to all processes
Sending SIGKILL to all processes
Requesting system reboot
***************************************************************
with fork() instead of vfork()
Freeing unused kernel memory: 68k init
*Start init_main
init: waiting for 10
*console_init
*init started
init started: BusyBox v1.10.0 (2008-04-01 22:01:03 CEST)
*single?
run_actions
init: before waitfor(run(a))
init: run fork returned 11
*call bb_signals
init: waiting for 11
init: run fork returned 0
...
init: after waitfor(run(a))
*signals
*RESPAWN
*ASKFIRST
init: before a->pid = run(a)
init: run fork returned 80
*call bb_signals
init: after a->pid = run(a)
init: before a->pid = run(a)
init: run fork returned 81
init: run fork returned 0
Please press Enter to activate this console. init: run fork returned 0
call bb_signals
init: after a->pid = run(a)
init: before a->pid = run(a)
init: run fork returned 82
BusyBox v1.10.0 (2008-04-01 22:01:03 CEST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
init: run fork returned 0
*call bb_signals
init: after a->pid = run(a)
init: before a->pid = run(a)
init: run fork returned 0
init: run fork returned 84
*call bb_signals
init: after a->pid = run(a)
init: before a->pid = run(a)
init: run fork returned 85
init: run fork returned 0
*call bb_signals
init: after a->pid = run(a)
init: before a->pid = run(a)
init: run fork returned 0
init: run fork returned 86
*call bb_signals
init: after a->pid = run(a)
*sleep(5)
correct TERM handler: 0x1004144c
TERM is not blocked
TERM is not pending
/ # ps -ef
PID USER VSZ STAT COMMAND
1 root 0 S init
2 root 0 S [keventd]
3 root 0 S [ksoftirqd_CPU0]
4 root 0 S [kswapd]
5 root 0 S [bdflush]
6 root 0 S [kupdated]
7 root 0 S [cifsoplockd]
8 root 0 S [mtdblockd]
9 root 0 S [rpciod]
21 root 0 S inetd
56 root 0 S [avia_av_wdt]
60 root 0 S [avia_gt_wdt]
80 root 0 S -/bin/sh
81 root 0 S init
82 root 0 S init
84 root 0 S init
85 root 0 S init
86 root 0 S init
87 root 0 R ps -ef
/ #
/ #
/ # halt
*HK: halt_reboot_pwoff
init: before waitfor(run(a))
init: run fork returned 89
init: run fork returned 0
*call bb_signals
init: waiting for 89
init: after waitfor(run(a))
The system is going down NOW!
init: waiting for 98
Sending SIGTERM to all processes
Sending SIGKILL to all processes
Requesting system halt
System halted.
*something => my debug printouts
Thanks four your help
Harald
More information about the busybox
mailing list