Если вы отправите SIGINT
, чье расположение по умолчанию - уничтожить процесс, процессу, который не блокирует и не обрабатывает его, процесс умрет.
Если вы хотите, чтобы сигнал прерывал блокирующие вызовы, например pause()
, он должен иметь обработчик.
Но простая установка обработчика вводит условия гонки:
if (c == 0 ){
//< if the signal arrives here the child dies
signal(SIGINT, handler);
//< if the signal arrives here then nothing happens except the handler is run
pause(); //< if the handler arrives here then pause gets interrupted
printf("signal was given\n");
exit(0);
}
Чтобы устранить условия гонки, вам нужно
- заблокировать сигнал в родительском так, чтобы ребенок начинал с заблокированного сигнала
- установить обработчик в дочерний элемент
- разблокируйте сигнал и
pause()
за один атомный шаг
Чтобы достичь 3. за один шаг, вам нужно sigsuspend()
вместо pause()
.
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
void handler(int Sig){}
int main()
{
sigset_t sigint, oldmask; sigemptyset(&sigint); sigaddset(&sigint, SIGINT);
sigprocmask(SIG_BLOCK, &sigint, &oldmask);
pid_t c=fork();
if(0>c) return perror(0),1;
if (c==0){
signal(SIGINT, handler);
sigdelset(&oldmask,SIGINT); /*in (the unlikely) case the process started with SIGINT blocked*/
sigsuspend(&oldmask);
printf("signal was given\n");
exit(0);
}
kill(c,SIGINT);
wait(0);
return 0;
}
Кроме того, вы можете использовать sigwait()
и вообще отказаться от использования обработчика:
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
int main()
{
sigset_t sigint, oldmask; sigemptyset(&sigint); sigaddset(&sigint, SIGINT);
sigprocmask(SIG_BLOCK, &sigint, &oldmask);
pid_t c=fork();
if(0>c) return perror(0),1;
if (c==0){
int sig; sigwait(&sigint,&sig);
printf("signal was given\n");
exit(0);
}
kill(c,SIGINT);
wait(0);
return 0;
}