2024-01-11
An old Unix mistake you could make when signaling init
(PID 1)
Init is the traditional name for the program that is run to be process ID 1, which is the ultimate ancestor of all Unix processes and historically in charge of managing the system. Process ID 1 is sufficiently crucial to the system that either it can't be killed or the system will reboot if it exits (or both, and this reboot is a hack). These days on Linux, PID 1 often isn't literally a binary and process called 'init', but the *BSDs have stuck with an 'init' binary.
Historically there have been a number of reasons for the system
administrator to send signals to init, which you can still see
documented for modern Unixes in places like the FreeBSD init(8)
manual page. One of them
was to reread the list of serial ports to offer login prompts on
and often in the process to re-offer logins on any ports init had
given up on, for example because the serial getty
on them was
starting and exiting too fast. Traditionally and even today, this
is done by sending init
a SIGHUP signal.
The kill
program has supported sending signals by name for a
long time, but sysadmins are lazy and we
tend to have memorized that SIGHUP is signal 1 (and signal 9 is
SIGKILL). So it was not unusual to type this as 'kill -1 1
',
sending signal 1 (SIGHUP) to process ID 1 (init). However, this
version is a bit dangerous, because it's one extra repeated character
away from a version with much different effects:
kill -1 -1
This is only one accidental unthinking repetition of '-1' (instead of typing '1') away from the version you want. Unfortunately the change is very bad.
(My view is that using 'kill -HUP 1' makes this much less likely because now you can't just repeat the '-1', although you can still reflexively type a '-' in front of both arguments.)
The destination process ID '-1' is very special, especially if
you're root at the time. In both kill(1)
and
the kill(2)
system call, using -1 as root means '(almost) all processes on the
system'. So the addition of one extra character, a repeat of one
you were just using, has turned this from sending a SIGHUP signal
to init
to sending a SIGHUP to pretty much every user and daemon
process that's currently running. Some of them will have harmless
reactions to this, like re-reading configuration files or re-executing
themselves, but many processes will exit abruptly, including some
number of daemon processes.
Back in the days when you were more likely to be SIGHUP'ing init in the first place, doing this by accident was not infrequently a good way to have to reboot your system. Even as recently as a decade ago, doing a 'kill -1 -1' as root by accident (for another reason) was a good way to have to reboot.
(At this point I can't remember if I ever accidentally made this mistake back in the old days, although I have typed 'kill -1 -1' in the wrong context.)