[Pkg-sysvinit-devel] Bug#397900: erroneous runlevel during boot-up sequence

Petter Reinholdtsen pere at hungry.com
Sun Nov 26 18:55:50 CET 2006


[Martin F Krafft]
> first off, I have no idea why you're escaping the space,

Me neither.  Probably historical reasons. :)

> and second, unfortunately, the result is not always correct; as a
> consequence, invoke-rc.d complains about being invoked during
> shutdown during system startup, because I asked my system to restart
> the ntp service via invoke-rc.d whenever the network link status
> changes (via a little shell script in /etc/network/if-up.d/.

When I run /sbin/runlevel during the rcS.d/ run, it return '2 6' here
too.  When I run it after rc2.d/ is executed, it return 'N 2'.  I have
no experience with the runlevel command, nor the invoke-rc.d command,
so I am quite unsure what the correct fix to this problem is.

Reading runlevel(8), I see that /sbin/runlevel is supposed to return
the previous and current system runlevel, presumably in that order.
It claim it should return 'N' if there was no previous runlevel.  I
guess the correct behaviour would be to return 'N S' or 'N N' while
rcS.d/ is executed, and 'S 2' or 'N 2' while rc2.d/ is executed.

The manual page claim that the runlevel information is also available
using 'who -r', and it seem to report a more correct runlevel when in
runlevel 2:

  # LANG=C who -r
           run-level 2  Nov  6 17:11                   last=S
  #

In runlevel S it returns this:

  # LANG=C who -r
           run-level 6  Nov 26 15:40                   last=2
  #

So who and runlevel seem to agree that the current runlevel is 6, and
the last one was 2.  The runlevel program is very simple, so I am not
sure where the bug can be located (compressed to save lines):

  int main(int argc, char **argv)
  {
    struct utmp *ut;  char prev;
    if (argc > 1) utmpname(argv[1]);
    setutent();
    while ((ut = getutent()) != NULL) {
          if (ut->ut_type == RUN_LVL) {
                  prev = ut->ut_pid / 256;
                  if (prev == 0) prev = 'N';
                  printf("%c %c\n", prev, ut->ut_pid % 256);
                  endutent();
                  exit(0);
          }
    }
    printf("unknown\n");
    endutent();
    return(1);
  }

It fetches the info from utmp.  Perhaps that file have incorrect
information in it?  I suspect runlevel 'S' isn't treated by init as a
real runlevel, and this make who and runlevel believe the current
runlevel is the runlevel used before the last reboot, aka runlevel 6.

Any ideas how we can change this to return more sensible values?  It
is hard to write to utmp at the start of the rcS.d/ run, as
/var/log/utmp isn't writable (and perhaps not even available) at that
time in the boot.

Friendly,
-- 
Petter Reinholdtsen




More information about the Pkg-sysvinit-devel mailing list