[PATCH] init.c, halt command not working

Denys Vlasenko vda.linux at googlemail.com
Thu Apr 3 18:06:27 PDT 2008


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


More information about the busybox mailing list