120 lines
5 KiB
Text
120 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
|