linux - threads - ¿Cómo se relaciona SIGINT con las otras señales de terminación?
posix windows (6)
Como DarkDust notó que muchas señales tienen los mismos resultados, los procesos pueden unirles diferentes acciones al distinguir cómo se genera cada señal. Al observar 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 entregan a cualquier hilo.
SA_KILL|SA_PROC, /* SIGINT */
SA_KILL|SA_PROC, /* SIGTERM */
En los sistemas POSIX, las señales de terminación generalmente tienen el siguiente orden (de acuerdo con muchas páginas MAN y la especificación POSIX):
SIGTERM: cortésmente pida que finalice un proceso. Terminará correctamente, limpiando todos los recursos (archivos, sockets, procesos secundarios, etc.), eliminando archivos temporales, etc.
SIGQUIT - solicitud más contundente. Terminará sin gracia, sigue limpiando los recursos que absolutamente necesitan limpieza, pero tal vez no elimine los archivos temporales, tal vez escriba información de depuración en alguna parte; en algún sistema también se escribirá un volcado del núcleo (independientemente de si la señal es capturada por la aplicación o no).
SIGKILL: petición más contundente. El proceso ni siquiera se pide que haga nada, pero el sistema limpiará el proceso, ya sea que así sea o no. Lo más probable es que se escriba un volcado del núcleo.
¿Cómo encaja SIGINT en esa imagen? Un proceso CLI usualmente es terminado por SIGINT cuando el usuario golpea CRTL + C, sin embargo, un proceso de fondo también puede ser terminado por SIGINT usando la utilidad KILL. Lo que no puedo ver en las especificaciones o en los archivos de encabezado es si SIGINT es más o menos enérgico que SIGTERM o si hay alguna diferencia entre SIGINT y SIGTERM en absoluto.
ACTUALIZAR:
La mejor descripción de las señales de terminación que encontré hasta ahora está en la documentación GNU LibC . Explica muy bien que existe una diferencia intencionada entre SIGTERM y SIGQUIT.
Dice sobre SIGTERM:
Es la forma normal de pedir cortésmente a un programa que finalice.
Y dice sobre SIGQUIT:
[...] y produce un volcado de núcleo cuando finaliza el proceso, al igual que una señal de error de programa. Puede pensar en esto como una condición de error del programa "detectada" por el usuario. [...] Ciertos tipos de limpiezas se omiten mejor al manejar SIGQUIT. Por ejemplo, si el programa crea archivos temporales, debe manejar las otras solicitudes de terminación eliminando los archivos temporales. Pero es mejor que SIGQUIT no los elimine, para que el usuario pueda examinarlos junto con el volcado del núcleo.
Y SIGHUP también se explica lo suficiente. SIGHUP no es realmente una señal de terminación, solo significa que la "conexión" al usuario se ha perdido, por lo que la aplicación no puede esperar que el usuario lea ningún resultado adicional (por ejemplo, la salida stdout / stderr) y no hay información que esperar de la usuario por más tiempo Para la mayoría de las aplicaciones eso significa que es mejor dejarlo. En teoría, una aplicación también podría decidir que entra en modo daemon cuando se recibe un SIGHUP y ahora se ejecuta como un proceso en segundo plano, escribiendo salida en un archivo de registro configurado. Para la mayoría de los daemons que ya se ejecutan en segundo plano, SIGHUP generalmente significa que deben volver a examinar sus archivos de configuración, por lo que lo envía a procesos en segundo plano después de editar los archivos de configuración.
Sin embargo, no hay una explicación útil de SIGINT en esta página, salvo que es enviada por CRTL + C. ¿Hay alguna razón por la cual uno manejaría SIGINT de una manera diferente que SIGTERM? Si es así, ¿qué razón sería esto y cómo sería el manejo diferente?
Con la excepción de algunas señales, los manejadores de señal pueden captar las diversas señales, o el comportamiento predeterminado al recibir una señal puede ser modificado. Consulte la página de manual de la signal(7)
para más detalles.
Después de una rápida búsqueda en Google de sigint vs sigterm , parece que la única diferencia entre los dos es si se inició mediante un atajo de teclado o mediante una llamada explícita para kill
.
Como resultado, podría, por ejemplo, interceptar sigint y hacer algo especial con él, sabiendo que probablemente se envió por un atajo de teclado. Tal vez actualice la pantalla o algo así, en lugar de morir (no recomendado, ya que la gente espera que ^C
mate el programa, solo un ejemplo).
También aprendí que ^/
debería enviar sigquit, que puedo comenzar a usar yo mismo. Parece muy útil.
SIGTERM y SIGKILL están destinados a solicitudes de "finalización de este proceso" de propósito general. SIGTERM (de forma predeterminada) y SIGKILL (siempre) provocarán la finalización del proceso. SIGTERM puede ser capturado por el proceso (por ejemplo, para que pueda hacer su propia limpieza si lo desea), o incluso ignorado por completo; pero SIGKILL no puede ser atrapado o ignorado.
SIGINT y SIGQUIT están diseñados específicamente para solicitudes desde el terminal: se pueden asignar caracteres de entrada particulares para generar estas señales (dependiendo de los ajustes de control del terminal). La acción predeterminada para SIGINT es el mismo tipo de finalización del proceso que la acción predeterminada para SIGTERM y la acción inmutable para SIGKILL; la acción predeterminada para SIGQUIT también es la terminación del proceso, pero pueden ocurrir acciones adicionales definidas por la implementación, como la generación de un volcado del núcleo. Cualquiera puede ser atrapado o ignorado por el proceso si es necesario.
SIGHUP, como usted dice, está destinado a indicar que la conexión de la terminal se ha perdido, en lugar de ser una señal de terminación como tal. Pero, de nuevo, la acción predeterminada para SIGHUP (si el proceso no detecta o 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 General Interface Interface incluye muchos más detalles sobre las señales relacionadas con la terminal.
Usando kill
(tanto la llamada del sistema como la utilidad ''puedes enviar casi cualquier señal a cualquier proceso, dado que tienes el permiso. Un proceso no puede distinguir cómo una señal cobró vida y quién la envió.
Dicho esto, SIGINT realmente pretende cantar la interrupción Ctrl-C, mientras que SIGTERM es la señal general de la terminal. No existe el concepto de que una señal sea "más enérgica", con la única excepción de que hay señales que no se pueden bloquear ni manejar (SIGKILL y SIGSTOP, de acuerdo con la página del manual).
Una señal solo puede ser "más enérgica" que otra señal con respecto a cómo un proceso receptor maneja la señal (y cuál es la acción predeterminada para esa señal). Por ejemplo, de forma predeterminada, tanto SIGTERM como SIGINT conducen a la terminación. Pero si ignora SIGTERM, entonces no terminará su proceso, mientras que SIGINT todavía lo hace.
Algunos son ANSI C y otros no
Una diferencia considerable es que:
- SIGINT y SIGTERM son ANSI C, por lo tanto más portátil
- SIGQUIT y SIGKILL no son
Se describen en la sección "7.14 Gestión de señales" del borrador C99 N1256 :
- Recibo 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 una Ctrl + C.