Solución:
SIGTERM y SIGKILL están destinados a solicitudes de “terminar este proceso” de propósito general. SIGTERM (por defecto) y SIGKILL (siempre) causarán la terminación del proceso. SIGTERM puede ser detectado por el proceso (por ejemplo, para que pueda hacer su propia limpieza si así lo desea), o incluso ignorado por completo; pero SIGKILL no se puede detectar ni ignorar.
SIGINT y SIGQUIT están diseñados específicamente para solicitudes del terminal: se pueden asignar caracteres de entrada particulares para generar estas señales (dependiendo de la configuración de control del terminal). La acción predeterminada para SIGINT es el mismo tipo de terminación de proceso que la acción predeterminada para SIGTERM y la acción inmutable para SIGKILL; la acción predeterminada para SIGQUIT es también la terminación del proceso, pero pueden ocurrir acciones adicionales definidas por la implementación, como la generación de un volcado de memoria. Cualquiera puede ser detectado o ignorado por el proceso si es necesario.
SIGHUP, como usted dice, está destinado a indicar que la conexión del terminal se ha perdido, en lugar de ser una señal de terminación como tal. Pero, nuevamente, la acción predeterminada para SIGHUP (si el proceso no lo detecta o lo ignora) es terminar el proceso de la misma manera que SIGTERM, etc.
Hay una tabla en las definiciones POSIX para signal.h
que enumera las diversas señales y sus acciones y propósitos predeterminados, y el capítulo Interfaz de terminal general incluye muchos más detalles sobre las señales relacionadas con el terminal.
Como señaló DarkDust, muchas señales tienen los mismos resultados, pero los procesos pueden adjuntar diferentes acciones al distinguir cómo se genera cada señal. Mirando el código fuente del kernel de FreeBSD (kern_sig.c) veo que las dos señales se manejan de la misma manera, terminan el proceso y se envían a cualquier hilo.
SA_KILL|SA_PROC, /* SIGINT */
SA_KILL|SA_PROC, /* SIGTERM */
man 7 signal
Esta es la conveniente página de manual no normativa del proyecto de páginas de manual de Linux que a menudo desea consultar para obtener información sobre señales de Linux.
La versión 3.22 menciona cosas interesantes como:
Las señales SIGKILL y SIGSTOP no se pueden capturar, bloquear ni ignorar.
y contiene la tabla:
Signal Value Action Comment
----------------------------------------------------------------------
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
SIGSEGV 11 Core Invalid memory reference
SIGPIPE 13 Term Broken pipe: write to pipe with no
readers
SIGALRM 14 Term Timer signal from alarm(2)
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at tty
SIGTTIN 21,21,26 Stop tty input for background process
SIGTTOU 22,22,27 Stop tty output for background process
que resume la señal Action
que distingue, por ejemplo, SIGQUIT de SIGQUIT, ya que SIGQUIT tiene acción Core
y SIGINT Term
.
Las acciones están documentadas en el mismo documento:
The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:
Term Default action is to terminate the process.
Ign Default action is to ignore the signal.
Core Default action is to terminate the process and dump core (see core(5)).
Stop Default action is to stop the process.
Cont Default action is to continue the process if it is currently stopped.
No puedo ver ninguna diferencia entre SIGTERM y SIGINT desde el punto de vista del kernel ya que ambos tienen acción Term
y ambos pueden ser atrapados. Parece que es solo una “distinción de convención de uso común”:
- SIGINT es lo que sucede cuando haces CTRL-C desde la terminal
- SIGTERM es la señal predeterminada enviada por
kill
Algunas señales son ANSI C y otras no
Una diferencia considerable es que:
- SIGINT y SIGTERM son ANSI C, por lo que son más portátiles
- SIGQUIT y SIGKILL no son
Se describen en el apartado “7.14 Manejo de señales” del borrador C99 N1256:
- Recepción SIGINT de una señal de atención interactiva
- SIGTERM una solicitud de terminación enviada al programa
lo que hace que SIGINT sea un buen candidato para un Ctrl + C interactivo.
POSIX 7
POSIX 7 documenta las señales con el signal.h
encabezado: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
Esta página también tiene la siguiente tabla de interés que menciona algunas de las cosas que ya habíamos visto en man 7 signal
:
Signal Default Action Description
SIGABRT A Process abort signal.
SIGALRM T Alarm clock.
SIGBUS A Access to an undefined portion of a memory object.
SIGCHLD I Child process terminated, stopped,
SIGCONT C Continue executing, if stopped.
SIGFPE A Erroneous arithmetic operation.
SIGHUP T Hangup.
SIGILL A Illegal instruction.
SIGINT T Terminal interrupt signal.
SIGKILL T Kill (cannot be caught or ignored).
SIGPIPE T Write on a pipe with no one to read it.
SIGQUIT A Terminal quit signal.
SIGSEGV A Invalid memory reference.
SIGSTOP S Stop executing (cannot be caught or ignored).
SIGTERM T Termination signal.
SIGTSTP S Terminal stop signal.
SIGTTIN S Background process attempting read.
SIGTTOU S Background process attempting write.
SIGUSR1 T User-defined signal 1.
SIGUSR2 T User-defined signal 2.
SIGTRAP A Trace/breakpoint trap.
SIGURG I High bandwidth data is available at a socket.
SIGXCPU A CPU time limit exceeded.
SIGXFSZ A File size limit exceeded.
BusyBox init
Predeterminado 1.29.2 de BusyBox reboot
El comando envía un SIGTERM a los procesos, duerme por un segundo y luego envía SIGKILL. Esta parece ser una convención común en diferentes distribuciones.
Cuando apaga un sistema BusyBox con:
reboot
envía una señal al proceso de inicio.
Entonces, el manejador de señales init termina llamando:
static void run_shutdown_and_kill_processes(void)
{
/* Run everything to be run at "shutdown". This is done _prior_
* to killing everything, in case people wish to use scripts to
* shut things down gracefully... */
run_actions(SHUTDOWN);
message(L_CONSOLE | L_LOG, "The system is going down NOW!");
/* Send signals to every process _except_ pid 1 */
kill(-1, SIGTERM);
message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
sync();
sleep(1);
kill(-1, SIGKILL);
message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
sync();
/*sleep(1); - callers take care about making a pause */
}
que imprime en la terminal:
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Aquí hay un ejemplo concreto mínimo de eso.
Señales enviadas por el kernel
- SIGKILL:
- Asesino de OOM: ¿Qué es RSS y VSZ en la gestión de memoria de Linux?