Procesos en C: Señales (SIGINT)

Desde hace un tiempo tengo la idea de escribir sobre el tema de procesos y señales en C.

Las señales se usan para la comunicación entre procesos y manipularlos. Un ejemplo muy conocido de señal es la señal SIGINT, que se envía cuando el usuario pulsa CTRL+C durante la ejecución de un programa. Cuando el programa que estamos ejecutando recibe esta señal finalizará su ejecución.

En el siguiente ejemplo vamos a ver cómo podemos hacer para que el programa realice alguna acción especial cuando el usuario pulse CTRL+C. La acción a ejecutar va a ser mostrar el mensaje: “¿Por qué me interrumpes?”:

// Para las funciones pause y alarm:
#include <unistd.h>
// Para las constantes SIGALRM y similares
#include <signal.h>
 
#include <stdio.h>
 
// Esta función es la que vamos a usar como controlador de la señal SIGINT
void despedida() {
	printf("------------------------\n");
	printf("¿Por qué me interrumpes?\n");
	printf("------------------------\n");
	raise(SIGTERM);
}
 
int main() {
 
	// Asociamos la señal SIGINT con la funcion "senal"
	signal(SIGINT, despedida);
 
	// Comenzamos un bucle que hará que el programa muestre sin
	// parar el mensaje "Nada nuevo por aquí"
	while(1) {
		printf("Nada nuevo por aquí.\n");
	}
}

En este programa, cuando el usuario pulse CTRL+C, en lugar de cerrarse directamente, se ejecutará la función que hemos asociado con esta señal (la funcion despedida).


La función despedida muestra el mensaje “¿Por qué me interrumpes?” y genera la señal SIGTERM (“raise” envía una señal al propio proceso). Si no hiciéramos esto el proceso no se detendría nunca (hasta que lo “matemos” con kill). Si te aburres haz la prueba con esta funcion:

void despedida() {
	printf("------------------------\n");
	printf("¿Por qué me interrumpes?\n");
	printf("------------------------\n");
}

Otra posibilidad es usar la función signal de nuevo para indicar al proceso que use la acción por defecto de SIGINT (SIG_DFL – Signal Default):

void despedida() {
	printf("------------------------\n");
	printf("¿Por qué me interrumpes?\n");
	printf("------------------------\n");
	signal(SIGINT, SIG_DFL); // Indicamos al programa que use la acción por defecto
	raise(SIGINT);
}

¿Pero por qué no podemos simplemente llamar a raise(SIGINT);?

Se podría pensar que bastaría con llamar a raise(SIGINT):

void despedida() {
	printf("------------------------\n");
	printf("¿Por qué me interrumpes?\n");
	printf("------------------------\n");
	raise(SIGINT);
}

El problema es que la señal SIGINT va a ser procesada por la función “despedida”. De esta forma, cuando pulsemos CTRL+C, se llamará a la función despedida. La función despedida genera de nuevo la señal SIGINT, que va a ser procesada de nuevo por ella misma. El resultado es que cuando pulsamos CTRL+c el proceso comenzará a ejecutar una y otra vez la función despedida mostrando el mensaje “¿Por qué me interrumpes?” sin parar.

¿Por qué? Cada vez que se pulse CTRL+C se ejecuta la función “despedida” en lugar de ejecutarse la acción por defecto (cerrar el programa).

Curso de programación en C para principiantes

Ejercicios de C resueltos y comentados

2 thoughts on “Procesos en C: Señales (SIGINT)

  1. Muy buena info aunque hace falta mas información sobre señales. Estaria bien que manejaras mas ejemplos. :)

Deja un comentario