Why do many Unix programs use signals like USR1?

2019-01-30 07:23发布

问题:

Many Unix programs accept signals like USR1 and USR2. For example, to upgrade the executable for Nginx on the fly, you send kill -USR2.

I understand that USR1 is a "user defined" signal, meaning that whoever created the program can use it to mean "shut down" or "dump your logs" or "print foo a thousand times" or whatever. But I don't understand why they must use this arbitrary name. Why not kill -UPGRADE, or kill -GRACEFUL_SHUTDOWN? Does Unix only allow specific signals?

While we're at it, Nginx also uses the following signals (see documentation):

  • TERM, INT: Quick shutdown
  • QUIT: Graceful shutdown
  • HUP:
    • Configuration reload
    • Start the new worker processes with a new configuration
    • Gracefully shutdown the old worker processes
  • USR1: Reopen the log files
  • USR2: Upgrade Executable on the fly
  • WINCH: Gracefully shutdown the worker processes

HUP? WINCH? What's the reason for these names? Where can I learn more about this?

回答1:

The signals available on an OS are defined by the OS (usually following POSIX) - they're not "strings" but rather integer constants with standard names. USR1 and USR2 are the two signals that have no attached specific meaning - intended for whatever arbitrary use the developer wants.

On your linux machine, read man 7 signal for an overview of signal handling and signals.

You can redefine the meaning of other signals if you're prepared to deal with the OS issuing those signals in response to events. You can e.g. make HUP mean "reload configuration" - as long as you're either certain that the process will never get a hangup (terminal loss), or you're prepared to handle cases where the OS and not a user sends the HUP signal.



回答2:

HUP is short for "hang-up". This signal is sent to a process if its controlling terminal reaches end-of-file. In the old days, controlling terminals were typically attached to serial ports, possibly via a modem link over a telephone line. If the telephone connection was hung up, the local modem would lower the Carrier Detect line, which would result in the kernel reporting end-of-file and a SIGHUP signal being sent.

WINCH is short for "window change". It is sent to a process if its controlling terminal changes size. For obvious reasons, terminals that can change size are usually pseudo-terminals ultimately represented by a terminal emulator running in a windowing environment (like xterm).



回答3:

Try kill -l and find the answer yourself:

1)  SIGHUP       2)  SIGINT       3)  SIGQUIT      4)  SIGILL       5)  SIGTRAP
6)  SIGABRT      7)  SIGBUS       8)  SIGFPE       9)  SIGKILL      10) SIGUSR1
11) SIGSEGV      12) SIGUSR2      13) SIGPIPE      14) SIGALRM      15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD      18) SIGCONT      19) SIGSTOP      20) SIGTSTP
21) SIGTTIN      22) SIGTTOU      23) SIGURG       24) SIGXCPU      25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF      28) SIGWINCH     29) SIGIO        30) SIGPWR
31) SIGSYS       34) SIGRTMIN     35) SIGRTMIN+1   36) SIGRTMIN+2   37) SIGRTMIN+3
38) SIGRTMIN+4   39) SIGRTMIN+5   40) SIGRTMIN+6   41) SIGRTMIN+7   42) SIGRTMIN+8
43) SIGRTMIN+9   44) SIGRTMIN+10  45) SIGRTMIN+11  46) SIGRTMIN+12  47) SIGRTMIN+13
48) SIGRTMIN+14  49) SIGRTMIN+15  50) SIGRTMAX-14  51) SIGRTMAX-13  52) SIGRTMAX-12
53) SIGRTMAX-11  54) SIGRTMAX-10  55) SIGRTMAX-9   56) SIGRTMAX-8   57) SIGRTMAX-7
58) SIGRTMAX-6   59) SIGRTMAX-5   60) SIGRTMAX-4   61) SIGRTMAX-3   62) SIGRTMAX-2
63) SIGRTMAX-1   64) SIGRTMAX


回答4:

Because the names of the signals are standardised (by POSIX). You can write your own kill-type executable to take -UPGRADE if you want and have it deliver the USR1 signal, but the standard kill that comes with UNIX will not recognise it.

Alternatively, you could create an alias, function or shell script to do the translation for you, such as with the bash alias:

alias upgrade='kill -USR1'

The signal.h header file maps the signal names to their actual values, which are implementation-dependent.

In terms of WINCH, I consider this a bit of an abomination. This is the signal that is delivered to applications when their window size changes (specifically when the window of their controlling terminal changes).

Using it to gracefully shut down worker threads is not a good idea unless you can guarantee the process will never run in a terminal. I know I'd be pretty miffed if I was running an application and it decided to cancel all work in flight just because I maximised the window :-)



回答5:

On POSIX-compliant platforms, SIGUSR1 and SIGUSR2 are signals sent to a process to indicate user-defined conditions. The symbolic constants for them are defined in the header file signal.h. Symbolic signal names are used because signal numbers can vary across platforms.

SIG is a common prefix for signal names. USR is an abbreviation for user-defined.



回答6:

Signal names originate from earlier times than Posix.

I want to talk about SIG**IOT**. In the times when DEC PDP mainframes were used, the processor(s) used had a special IOT instruction (I/O Trap) which was often used to gently crash the system--usually forcing it to reboot (in realtime servers). The whole kernel along with the device drivers, and privileged processes, (written in assembler), used this method. Even today, there are processors that still have this IOT instruction.

So, when kernel experiences an execution of an IOT instruction in unprivileged domain, it raises a SIGIOT to the affected process.