Desarrollo de aplicaciones Linux y manejo de señales.

Desarrollo de aplicaciones Linux y manejo de señales.

Actualmente tengo problemas con mis usuarios quejándose de la finalización de mi aplicación. Bajo algunas condiciones (aparentemente arbitrarias) y entornos de escritorio, la aplicación no finaliza y la configuración no se guarda al reiniciar. Pregunté en los canales de irc correspondientes y la mayoría de las veces me dicen que maneje las señales correctamente. Conozco SIGINT para Ctrl-C en la terminal y SIGTERM para la terminación "normal". Pero me dijeron que SIGHUP también es importante. Entonces mi pregunta es:

¿Qué señales tengo que manejar para crear una aplicación que se comporte bien?

Respuesta1

https://en.wikipedia.org/wiki/Unix_signal

tiene una lista de señales estándar y sus acciones predeterminadas. Cualquier proceso con privilegios suficientes siempre puede enviarle cualquier señal, pero los procesos (o usted, a través de los procesos) no deberían hacer esto.

Solo debe killy esperar que sus procesos se editen killconTÉRMINOy un montón de señales que puede generar su entorno (el shell, el controlador del terminal), a menos que sepa que el objetivo maneja la señal especial que desea enviar.

Puede ordenar las señales básicas por sus acciones.

Las señales de coredumping

ABRT TRAP SYS BUS FPE ILL SEGV   XFSZ XCPU QUIT

son generados por usted (TRAP, ABRT, SYS) utilizando algunas funciones especializadas o por entrar en estados de error grave (BUS, FPE, ILL, SEGV). QUITes generado por un usuario en una terminal que desea un volcado de núcleo ( C+\).

Es posible que desee mantenerlos en sus disposiciones predeterminadas.

Fuera deseñales de terminación:

HUP INT PIPE TERM ALRM POLL PROF USR1 USR2

deberías esperar

HUP INT PIPE TERM

de su entorno en diversas circunstancias:

HUP -- when the terminal hungs up or you become a stopped orphaned process
INT -- when the user at the terminal interrupts you with C-c
PIPE -- when a PIPE or socket you write into closes, e.g. by
        exiting before you finished writing to it 
       (`yourprogram | (exit)` will give you a `PIPE` 
        if yourprogram attempts to write to its STDOUT) 
TERM -- when a process ends you a normal termination request

Debería recibir el resto de las señales de terminación sólo si lo configura usted mismo.

MATARyDETENERno puedes hacer nada al respecto.

Es posible que desees interceptar el terminal generado.señales de parada:

TTIN -- you read from the terminal and you're a backgrounded process
TTOU -- you write the terminal when you're a backgrounded process
        and the terminal is set to put you to sleep when you do
TSTP -- you're being put to sleep with `C-Z`

pero en el peor de los casos, estos simplemente detendrán su proceso, sin corromper su estado.

A menos que sepa que necesita manejar CHLD, CONTo URGno lo hace.

TL;DR:

Básicamente, creo que HUP, INT, PIPE y TERM deben manejarse (o ignorarse) si normalmente desea realizar una limpieza previa a la salida. El resto se puede dejar en paz, a menos que su programa utilice esas señales, o a menos que necesite absolutamente alguna limpieza en todas las circunstancias.

En el último caso, puede bloquear en blanco todas las señales no controladas, pero tenga en cuenta que las máscaras de bloqueo de señales se heredan a través de bifurcaciones y llamadas ejecutivas e ignoran o bloquean señales como ILL, si surgieron de la ejecución de su proceso y no se le enviaron. por kill o sigqueue le dará un comportamiento indefinido.

Si desea obtener más información, explore las páginas de manual y los estándares. Las señales son un tema bastante importante en Unix y manejarlas puede resultar muy complicado.

Respuesta2

Si sigue ese camino, probablemente terminará ignorando un buen número de señales, simplemente porque una de ellas está finalizando su programa. Como sugiere sablynx en un comentario, el mejor curso de acción sería analizar estas señales y comprender de dónde provienen. Después de todo, puede haber una buena razón para que su programa sea eliminado.

Dicho esto, puedes echar un vistazo asignals(7)para obtener una lista de señales que pueden provocar la terminación del proceso:

SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGKILL, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1 y SIGUSR2.

Si su aplicación pasa algún tiempo conectada a una terminal, su manejo SIGINTes una buena idea ( Ctrl+ Ces bastante famoso después de todo). SIGTERMTambién es una buena idea porque sigue siendo la señal de terminación básica y es utilizada por el núcleo (por ejemplo, al apagar el sistema). SIGQUITEs probablemente la versión "más dura" de las dos anteriores, ya que provoca un volcado del núcleo. Cuando reciba ese, probablemente debería esperarse que su programa falle de inmediato. Al recibir cualquiera de los demás, se esperaría que su programa "limpiara su desorden y se fuera" (guarde la configuración, finalice correctamente).

SIGILL, SIGFPEy SIGSEGVson SIGPIPEseñales relacionadas con el mal comportamiento del programa.Fallo de segmentaciónEsta es probablemente la situación más recurrente, pero al final, todos estos casos pueden tratarse como errores y no creo que captar la señal sea la mejor manera de recuperarse de estas situaciones.

  • La mayoría de las veces, los compiladores no permiten que SIGILLesto suceda tan fácilmente (más aquí) así que creo que puedes dejar eso a un lado.
  • Asegúrate de nunca dividir por cero y evitarás la mayoría de SIGFPElas s. Aparte de eso, sólo asegúrese de que su programa sea bueno en matemáticas y no se vuelva loco con los números.
  • SIGSEGVpuede ser causado por varias cosas (acceso ilegal a la memoria, eliminación de barreras ilegales), y para eso sugeriría usarlo gdbpara vigilar su programa mientras se ejecuta y rastrear la instrucción desagradable usando gdbla pila.
  • Por último, SIGPIPEestá relacionado principalmente con flujos de datos (lectura de archivos, conexiones,...). Si es probable que alguna de las secuencias de E/S de su programa finalice mientras se ejecuta, debe asegurarse de que su programa verifique sus descriptores antes de usarlos y maneje todos los eventos de E/S que ocurran en él (al usar selecto poll, por ejemplo). gdbpodría ser útil aquí también.

SIGABRT, SIGALRMy son básicamente señales de usuario SIGUSR1. SIGUSR2Si los estás recibiendo, es probable que realmente hayas hecho que eso suceda.

Esto nos deja con SIGHUPy SIGKILL, que es posible que no se detecten.

  • SIGHUPocurrirá, por ejemplo, si inicia el proceso desde una terminal y luego cierra esa terminal sin desconectar el proceso ( disowno usar nohup). Si su programa se inicia desde la terminal y se ejecuta como un demonio, no olvide separarlo del shell, por ejemplo mediante una doble bifurcación. Esta señal particular es menos relevante si su programa puede iniciarse desde una GUI, o en el momento del arranque, donde es menos probable que el terminal de control esté "cerrado".

  • SIGKILLcomo sabes, es el todopoderoso de las señales. Es la forma que tiene el núcleo de decir "¡mierda!". Si estás recibiendo eso, entonces debes centrar tu atención en lo que sea que esté emitiendo la señal, en lugar de cómo manejarlo en tu programa.

Al final, analizar la señal y utilizar herramientas de depuración es probablemente el enfoque más sencillo para estos problemas. Si el kernel activa una señal cuando su programa se comporta mal, gdbdebería ayudarle a localizar el problema. En ese caso, olvídate de la señal y concéntrate en el error del que te habla.

Si la señal proviene del "exterior", encontrar el emisor probablemente sea el mejor curso de acción.(si realmente no puedes encontrarlo,rastreoelkill(2)la llamada al sistema podría ser un buen último recurso). Luego podrás decidir si quieres ignorarlo ( SIG_IGN), o tenerlo en cuenta. Silenciar el programa emisor también puede ser una buena alternativa...

información relacionada