Buscar..


Sintaxis

  • void (* señal (int sig, void (* func) (int))) (int);

Parámetros

Parámetro Detalles
sig La señal para configurar el manejador de señales en, uno de SIGABRT , SIGFPE , SIGILL , SIGTERM , SIGINT , SIGSEGV o algún valor definido de implementación
función El controlador de señales, que es uno de los siguientes: SIG_DFL , para el controlador predeterminado, SIG_IGN para ignorar la señal, o un puntero de función con la firma void foo(int sig); .

Observaciones

El uso de manejadores de señales con solo las garantías del estándar C impone varias limitaciones que pueden o no pueden hacerse en el manejador de señales definido por el usuario.

  • Si la función definida por el usuario regresa mientras se maneja SIGSEGV , SIGFPE , SIGILL o cualquier otra interrupción de hardware definida por la implementación, el comportamiento no está definido por el estándar C. Esto se debe a que la interfaz de C no proporciona medios para cambiar el estado defectuoso (p. Ej., Después de una división por 0 ) y, por lo tanto, cuando el programa regresa se encuentra exactamente en el mismo estado erróneo que antes de que ocurriera la interrupción del hardware.

  • Si se llamó a la función definida por el usuario como resultado de una llamada para abort o raise , el manejador de señal no tiene permitido llamar raise , nuevamente.

  • Las señales pueden llegar a la mitad de cualquier operación y, por lo tanto, la indivisibilidad de las operaciones generalmente no puede garantizarse ni el manejo de la señal funciona bien con la optimización. Por lo tanto, todas las modificaciones a los datos en un controlador de señales deben ser a variables

    • de tipo sig_atomic_t (todas las versiones) o un tipo atómico sin bloqueo (desde C11, opcional)
    • que son volatile calificados.
  • Otras funciones de la biblioteca estándar de C generalmente no respetarán estas restricciones, ya que pueden cambiar las variables en el estado global del programa. El estándar de C sólo hace garantías para abort , _Exit (desde C99), quick_exit (desde C11), signal (para el mismo número de señal), y algunas operaciones atómicas (desde C11).

El comportamiento no está definido por el estándar C si se viola alguna de las reglas anteriores. Las plataformas pueden tener extensiones específicas, pero estas generalmente no son portátiles más allá de esa plataforma.

  • Por lo general, los sistemas tienen su propia lista de funciones que son seguras para señales asíncronas , es decir, funciones de biblioteca C que pueden usarse desde un controlador de señales. Por ejemplo, a menudo printf está entre estas funciones.

  • En particular, el estándar C no define mucho sobre la interacción con su interfaz de subprocesos (desde C11) o cualquier biblioteca de subprocesos específica de la plataforma, como los subprocesos POSIX. Dichas plataformas deben especificar la interacción de dichas bibliotecas de hilos con señales por sí mismas.

Manejo de señales con “señal ()”

Los números de señal pueden ser sincrónicos (como SIGSEGV - falla de segmentación) cuando se activan por un mal funcionamiento del programa en sí mismo o asíncronos (como SIGINT - atención interactiva) cuando se inician desde fuera del programa, por ejemplo, al Cntrl-C una tecla como Cntrl-C .

La función signal() es parte del estándar ISO C y se puede usar para asignar una función para manejar una señal específica

#include <stdio.h>  /* printf() */
#include <stdlib.h> /* abort()  */
#include <signal.h> /* signal() */

void handler_nonportable(int sig)
{
    /* undefined behavior, maybe fine on specific platform */
    printf("Catched: %d\n", sig);
    
    /* abort is safe to call */
    abort();
}

sig_atomic_t volatile finished = 0;

void handler(int sig)
{
    switch (sig) {
    /* hardware interrupts should not return */
    case SIGSEGV:
    case SIGFPE:
    case SIGILL:
C11
      /* quick_exit is safe to call */
      quick_exit(EXIT_FAILURE);
C11
      /* use _Exit in pre-C11 */
      _Exit(EXIT_FAILURE);
    default:
       /* Reset the signal to the default handler, 
          so we will not be called again if things go
          wrong on return. */
      signal(sig, SIG_DFL);
      /* let everybody know that we are finished */
      finished = sig;
      return;
   }
}

int main(void)
{

    /* Catch the SIGSEGV signal, raised on segmentation faults (i.e NULL ptr access */
    if (signal(SIGSEGV, &handler) == SIG_ERR) {
        perror("could not establish handler for SIGSEGV");
        return EXIT_FAILURE;
    }

    /* Catch the SIGTERM signal, termination request */
    if (signal(SIGTERM, &handler) == SIG_ERR) {
        perror("could not establish handler for SIGTERM");
        return EXIT_FAILURE;
    }

    /* Ignore the SIGINT signal, by setting the handler to `SIG_IGN`. */
    signal(SIGINT, SIG_IGN);


    /* Do something that takes some time here, and leaves
       the time to terminate the program from the keyboard. */

    /* Then: */

    if (finished) {
       fprintf(stderr, "we have been terminated by signal %d\n", (int)finished);
        return EXIT_FAILURE;
    }


    /* Try to force a segmentation fault, and raise a SIGSEGV */
    {
      char* ptr = 0;
      *ptr = 0;
    }

    /* This should never be executed */
    return EXIT_SUCCESS;
}

El uso de signal() impone importantes limitaciones a lo que se le permite hacer dentro de los manejadores de señales, consulte las observaciones para obtener más información.

POSIX recomienda el uso de sigaction() lugar de signal() , debido a su comportamiento subespecificado y variaciones significativas en la implementación. POSIX también define muchas más señales que el estándar ISO C, incluyendo SIGUSR1 y SIGUSR2 , que el programador puede usar libremente para cualquier propósito.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow