a06e2ab395
import/switch of: init, getty, reboot, halt, shutdown, wall, last changes: . change reboot() call to netbsd prototype and args . allows pristine <utmp.h> . use clean <sys/reboot.h> instead of <minix/reboot.h> . implement TIOCSCTTY for use by getty so getty can get controlling terminal from init's child(ren) . allow NULL envp for exec Change-Id: I5ca02cb4230857140c08794bbfeba7df982c58a3
119 lines
5 KiB
Text
119 lines
5 KiB
Text
$NetBSD: NOTES,v 1.3 2006/04/18 11:40:26 salo Exp $
|
|
|
|
POSIX and init:
|
|
--------------
|
|
|
|
POSIX.1 does not define 'init' but it mentions it in a few places.
|
|
|
|
B.2.2.2, p205 line 873:
|
|
|
|
This is part of the extensive 'job control' glossary entry.
|
|
This specific reference says that 'init' must by default provide
|
|
protection from job control signals to jobs it starts --
|
|
it sets SIGTSTP, SIGTTIN and SIGTTOU to SIG_IGN.
|
|
|
|
B.2.2.2, p206 line 889:
|
|
|
|
Here is a reference to 'vhangup'. It says, 'POSIX.1 does
|
|
not specify how controlling terminal access is affected by
|
|
a user logging out (that is, by a controlling process
|
|
terminating).' vhangup() is recognized as one way to handle
|
|
the problem. I'm not clear what happens in Reno; I have
|
|
the impression that when the controlling process terminates,
|
|
references to the controlling terminal are converted to
|
|
references to a 'dead' vnode. I don't know whether vhangup()
|
|
is required.
|
|
|
|
B.2.2.2, p206 line 921:
|
|
|
|
Orphaned process groups bear indirectly on this issue. A
|
|
session leader's process group is considered to be orphaned;
|
|
that is, it's immune to job control signals from the terminal.
|
|
|
|
B.2.2.2, p233 line 2055:
|
|
|
|
'Historically, the implementation-dependent process that
|
|
inherits children whose parents have terminated without
|
|
waiting on them is called "init" and has a process ID of 1.'
|
|
|
|
It goes on to note that it used to be the case that 'init'
|
|
was responsible for sending SIGHUP to the foreground process
|
|
group of a tty whose controlling process has exited, using
|
|
vhangup(). It is now the responsibility of the kernel to
|
|
do this when the controlling process calls _exit(). The
|
|
kernel is also responsible for sending SIGCONT to stopped
|
|
process groups that become orphaned. This is like old BSD
|
|
but entire process groups are signaled instead of individual
|
|
processes.
|
|
|
|
In general it appears that the kernel now automatically
|
|
takes care of orphans, relieving 'init' of any responsibility.
|
|
Specifics are listed on the _exit() page (p50).
|
|
|
|
On setsid():
|
|
-----------
|
|
|
|
It appears that neither getty nor login call setsid(), so init must
|
|
do this -- seems reasonable. B.4.3.2 p 248 implies that this is the
|
|
way that 'init' should work; it says that setsid() should be called
|
|
after forking.
|
|
|
|
Process group leaders cannot call setsid() -- another reason to
|
|
fork! Of course setsid() causes the current process to become a
|
|
process group leader, so we can only call setsid() once. Note that
|
|
the controlling terminal acquires the session leader's process
|
|
group when opened.
|
|
|
|
Controlling terminals:
|
|
---------------------
|
|
|
|
B.7.1.1.3 p276: 'POSIX.1 does not specify a mechanism by which to
|
|
allocate a controlling terminal. This is normally done by a system
|
|
utility (such as 'getty') and is considered ... outside the scope
|
|
of POSIX.1.' It goes on to say that historically the first open()
|
|
of a tty in a session sets the controlling terminal. P130 has the
|
|
full details; nothing particularly surprising.
|
|
|
|
The glossary p12 describes a 'controlling process' as the first
|
|
process in a session that acquires a controlling terminal. Access
|
|
to the terminal from the session is revoked if the controlling
|
|
process exits (see p50, in the discussion of process termination).
|
|
|
|
Design notes:
|
|
------------
|
|
|
|
your generic finite state machine
|
|
we are fascist about which signals we elect to receive,
|
|
even signals purportedly generated by hardware
|
|
handle fatal errors gracefully if possible (we reboot if we goof!!)
|
|
if we get a segmentation fault etc., print a message on the console
|
|
and spin for a while before rebooting
|
|
(this at least decreases the amount of paper consumed :-)
|
|
apply hysteresis to rapidly exiting gettys
|
|
check wait status of children we reap
|
|
don't wait for stopped children
|
|
don't use SIGCHILD, it's too expensive
|
|
but it may close windows and avoid races, sigh
|
|
look for EINTR in case we need to change state
|
|
init is responsible for utmp and wtmp maintenance (ick)
|
|
maybe now we can consider replacements? maintain them in parallel
|
|
init only removes utmp and closes out wtmp entries...
|
|
|
|
necessary states and state transitions (gleaned from the man page):
|
|
1: single user shell (with password checking?); on exit, go to 2
|
|
2: run rc script, on exit 0 check if init.root sysctl != "/", if it
|
|
differs then fork + chroot into the value of init.root and run
|
|
/etc/rc inside the chroot: on exit 0, go to 3; on exit N (error),
|
|
go to 1 (applies also to /etc/rc when init.root == "/")
|
|
3: read ttys file: on completion, go to 4. If we did chroot in
|
|
state 2, we chroot after forking each getty to the same dir
|
|
(init.root is not re-read)
|
|
4: multi-user operation: on SIGTERM, go to 7; on SIGHUP, go to 5;
|
|
on SIGTSTP, go to 6
|
|
5: clean up mode (re-read ttys file, killing off controlling processes
|
|
on lines that are now 'off', starting them on lines newly 'on')
|
|
on completion, go to 4
|
|
6: boring mode (no new sessions); signals as in 4
|
|
7: death: send SIGHUP to all controlling processes, reap for 30 seconds,
|
|
then go to 1 (warn if not all processes died, i.e. wait blocks)
|
|
Given the -s flag, we start at state 1; otherwise state 2
|