1 Вопрос: Почему SIGINT перестает спать больше одного раза?

вопрос создан в Wed, May 8, 2019 12:00 AM

Я не понимаю, почему после первого выполнения функции kill функция сна не приостанавливает родительский процесс. После доставки SIGINT генерируется много процессов. Кроме того, кажется, что генерируется переменное количество процессов. Требуется ли обработчик для SIGINT для очистки первого SIGINT от ожидающих сигналов?

void handler(int s) {
    int status;
    wait(&status);
    printf("\n in the handler");
    if (WIFSIGNALED(status)) {
        int sig=WTERMSIG(status);
        printf("\n child stopped by signal %d\n",sig);
    }
    if (WIFEXITED(status)) {
        int ex=WEXITSTATUS(status);
        printf("\n child stopped with exist status %d\n",ex);
    }
}

int main() {
    int pid,len, count, ret;
    char s[1024];
    signal(SIGCHLD,handler);
    while(1) {
        pid=fork();
        if (pid==0) {
            printf("\n Write something ");
            scanf("%s",s);
            len=strlen(s);
            printf("\n Characters: %d",len);
            return 1;
        }
        else {
            sleep(20);
            kill(pid,SIGINT);
        }
    }
}
    
1
  1. Попробуйте запустить с strace, чтобы увидеть, что происходит.
    2019-05-08 16: 30: 40Z
  2. Две возможные проблемы. Во-первых, вы не можете безопасно вызывать printf() в обработчике сигналов, так как это не безопасно для асинхронных сигналов. Смотрите stackoverflow.com/questions/34467694/… для одного примера вопроса. Во-вторых, вы можете использовать sigaction() вместо signal() .
    2019-05-08 16: 58: 54Z
1 ответ                              1                         

SIGCHLD из предыдущего kill, вызывающего смерть ребенка, прибывает именно тогда, когда вы находитесь в следующем sleep.

Сон - это прерываемая функция. Если обработчик сигнала работает, когда ваш поток в нем, sleep будет прерван. Итак, вы переходите к следующему kill, который косвенно вызовет еще один SIGCHLD, который, скорее всего, произойдет, когда ваша следующая итерация спит, что приведет к нескольким пропущенным снам.

Если вы вставите sleep(1) до fork(), он должен (практически) сместить время вправо так, чтобы следующий sleep(20); не прерывался.

(Я отношусь к этому как к быстрому и грязному эксперименту. Ни в коем случае не стоит полагаться на подобные «корректировки» в производственном коде (или в этом случае использовать printf в обработчиках сигналов). ) р>     

2
2019-05-08 23: 15: 40Z
  1. Также может помочь выполнение { int t = 20; while (0 <= (t = sleep(t))); } вместо sleep(20);.
    2019-05-09 04: 56: 19Z
  2. t выше должно быть unsigned int.
    2019-05-09 05: 30: 05Z
источник размещен Вот