Si está generando el SIGINT
con Ctrl +C en un sistema Unix, la señal se envía a todo el grupo de procesos.
Debe usar setpgid o setsid para colocar el proceso secundario en un grupo de procesos diferente para que no reciba las señales generadas por el terminal de control.
[Editar:]
Asegúrese de leer la sección JUSTIFICACIÓN del setpgid
página cuidadosamente. Es un poco complicado incluir todas las posibles condiciones de carrera aquí.
Para garantizar al 100% que ningún SIGINT
será entregado a su proceso secundario, debe hacer algo como esto:
#define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ }
/* Block SIGINT. */
sigset_t mask, omask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0);
/* Spawn child. */
pid_t child_pid = fork();
CHECK(child_pid >= 0);
if (child_pid == 0) {
/* Child */
CHECK(setpgid(0, 0) == 0);
execl(...);
abort();
}
/* Parent */
if (setpgid(child_pid, child_pid) < 0 && errno != EACCES)
abort(); /* or whatever */
/* Unblock SIGINT */
CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0);
Estrictamente hablando, cada uno de estos pasos es necesario. Tienes que bloquear la señal en caso de que el usuario presione Ctrl +C justo después de la llamada a fork
. Tienes que llamar al setpgid
en el niño en caso de que el execl
ocurre antes de que el padre tenga tiempo de hacer algo. Tienes que llamar al setpgid
en el padre en caso de que el padre se ejecuta y alguien presiona Ctrl +C ante el niño tiene tiempo para hacer cualquier cosa.
La secuencia anterior es torpe, pero maneja el 100 % de las condiciones de carrera.