[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