2015-11-03 1 views
0

Я пытаюсь обрабатывать сигналы SIGTERM и SIGUSR1 между 4 процессами (3 детей + 1 отец), но я не знаю, почему signal() не вызывает обработчик. Может кто-нибудь мне помочь?Почему сигнал системного вызова() не вызывает вызов обработчика?

Это выход, как я ожидал:

pid of father of all: 13192 
The father 13192 is waiting to all children die to too 
Child1: pid = 13196 - parent's pid: 13192 
Child2: pid = 13197 - parent's pid: 13192 
Child3: pid = 13198 - parent's pid: 13192 
Sending user signal 
user signal sent 
Into the interrupt_handler 
The child1 13196 is going to be killed immediately 
The child2 13197 is going to be killed later 
The child2 13197 is going to kill itself now 
Child3: pid = 13198 - parent's pid: 13192 
Sending user signal 
user signal sent 
Into the interrupt_handler 
The child3 13198 is going to be killed immediately 

Это выход я получаю:

pid of father of all: 13192 
The father 13192 is waiting to all children die to too 
Child1: pid = 13196 - parent's pid: 13192 
Child2: pid = 13197 - parent's pid: 13192 
Child3: pid = 13198 - parent's pid: 13192 
Sending user signal 
user signal sent 
Child1: pid = 13196 - parent's pid: 13192 
Child2: pid = 13197 - parent's pid: 13192 
Child3: pid = 13198 - parent's pid: 13192 
Sending user signal 
user signal sent 
Child1: pid = 13196 - parent's pid: 13192 
... 

Как вы можете видеть, INTERRUPT_HANDLER не была вызвана для обработки сигнала. Это проблема.

Вот весь мой код:

#include <errno.h>    // errno and error codes 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h>    // for fork() 
#include <stddef.h> 
#include <float.h> 
#include <sys/types.h>   // for wait() 
#include <sys/stat.h> 
#include <sys/ipc.h>   // for all IPC function calls 
#include <sys/shm.h>   // for shmget(), shmat(), shmctl() 
#include <sys/sem.h>   // for semget(), semop(), semctl() 
#include <sys/wait.h>   // for wait() 
#include <sys/unistd.h> 
#include <signal.h>    // for kill(), sigsuspend(), others 

pid_t child1, child2, child3; 

int count_tens=0; 

void interrupt_handler(int signal){ 

    printf("Into the interrupt_handler\n"); 

    if (signal==SIGUSR1) 
    { 
     count_tens++; 

     if(count_tens==1) 
     { 
      printf("The child1 %d is going to be killed immediately\n",getpid()); 
      if(!kill(child1,SIGKILL)) 
       perror("Did not kill (1)");//kills child1 
      printf("The child2 %d is going to be killed later\n",getpid()); 
      if(!kill(child2,SIGTERM)) 
       perror("Did not kill (2)");//let the child2 goes through interrupt_handler 

     } else if(count_tens==2) 
     { 
      printf("The child3 %d is going to be killed immediately\n",getpid()); 
      //main(); //restart application 
      raise(SIGKILL); //child3 dies. At this point all children have died. 

     } 
    } 

    if (signal==SIGTERM){ 
     printf("The child2 %d is going to kill itself now\n",getpid()); 
     raise(SIGKILL); 
    } 
} 

int main(){ 

    if ((signal(SIGTERM, interrupt_handler) == SIG_ERR) || (signal(SIGUSR1, interrupt_handler) == SIG_ERR)) { 
     printf("Error while setting a signal handler\n"); 
     exit(EXIT_FAILURE); 
    } 

    child1=fork(); 
    if (child1<0) { perror("fork"); exit(errno);} 
    if(child1==0){ 
     while(1){ 
      sleep(4); 
      printf("Child1: pid = %d - parent's pid: %d\n",getpid(),getppid()); 
     } 
    } 

    child2=fork(); 
    if(child2<0) { perror("fork"); exit(errno);} 
    if(child2==0){ 
     while(1){ 
      sleep(5); 
      printf("Child2: pid = %d - parent's pid: %d\n",getpid(),getppid()); 
     } 
    } 

    child3=fork(); 
    if(child3<0) { perror("fork"); exit(errno);} 
    if(child3==0){ 
     while(1){ 
      sleep(6); 
      printf("Child3: pid = %d - parent's pid: %d\n",getpid(),getppid()); 
      printf("Testando: Child1 pid = %d, Child2 pid = %d, Child3 pid = %d\n",child1,child2,child3); 
       printf("Sending user signal\n"); 
       kill(getppid(), SIGUSR1); 
       printf("user signal sent\n"); 
     } 
    } 

    printf("pid of father of all: %d\n",getpid()); 
    printf("The father %d is waiting to all children die to too\n",getpid()); 
    waitpid(child3, NULL, 0); // PARENT blocks until 3th CHILD ends 
    return 0; 
} 
+0

Когда 'ожидания()' прерывается сигналом, он возвращает '-1' с' errno' установлен в 'EINTR'. Таким образом, цикл while в конце будет завершен после первого сигнала. – Barmar

+0

@Barmar, спасибо за ответ. Я прокомментировал строку while (wait (NULL)! = - 1); и теперь, когда я запускаю программу, мой ubuntu выходит из системы автоматически. Кажется, мое приложение выдает SO. Как мне исправить? Я имею ограниченное знание этих вещей. Я был бы очень рад вашей помощи. ТКС! –

+0

Если вы закомментируете цикл, родительскому процессу больше нечего делать после того, как он разворачивает всех детей, поэтому он завершает работу. – Barmar

ответ

0

Обработчик будет выполняться процесс, который получил сигнал.

Чтобы убить ребенка3 kill(child3,SIGKILL) можно использовать вместо raise(SIGKILL);.

При первом сигнале в этой программе, обработчик будет вызываться отцом, потому что отец получил первый сигнал (SIGUSR1), поэтому raise(SIGKILL); отец убивает себя.

Вот весь код:

#include <errno.h>    // errno and error codes 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h>    // for fork() 
#include <stddef.h> 
#include <float.h> 
#include <sys/types.h>   // for wait() 
#include <sys/stat.h> 
#include <sys/ipc.h>   // for all IPC function calls 
#include <sys/shm.h>   // for shmget(), shmat(), shmctl() 
#include <sys/sem.h>   // for semget(), semop(), semctl() 
#include <sys/wait.h>   // for wait() 
#include <sys/unistd.h> 
#include <signal.h>    // for kill(), sigsuspend(), others 

pid_t child1, child2, child3; 

int count_tens=0; 

void interrupt_handler(int signal){ 

    printf("Into the interrupt_handler\n"); 

    if (signal==SIGUSR1) 
    { 
     count_tens++; 

     if(count_tens==1) 
     { 
      printf("The child1 %d is going to be killed immediately\n",child1); 
      if(kill(child1,SIGKILL)==-1) 
       perror("Did not kill (1)");//kills child1 
      printf("The child2 %d is going to be killed later\n",child2); 
      if(kill(child2,SIGTERM)==-1) 
       perror("Did not kill (2)");//let the child2 goes through interrupt_handler 

     } else if(count_tens==2) 
     { 
      printf("The child3 %d is going to be killed immediately\n",child3); 
      //main(); //restart application 
      if(kill(child3,SIGKILL)==-1) 
       perror("Did not kill (3)");//kills child3. At this point all children have died. 
     } 
    } 

    if (signal==SIGTERM){ 
     printf("The child2 %d is going to be killed now\n",getpid()); 
     if(raise(SIGKILL)==-1) 
      perror("Did not kill (4)");//let the child2 goes through interrupt_handler 
    } 
} 

int main(){ 

    if ((signal(SIGTERM, interrupt_handler) == SIG_ERR) || (signal(SIGUSR1, interrupt_handler) == SIG_ERR)) { 
     printf("Error while setting a signal handler\n"); 
     exit(EXIT_FAILURE); 
    } 

    child1=fork(); 
    if (child1<0) { perror("fork"); exit(errno);} 
    if(child1==0){ 
     while(1){ 
      sleep(4); 
      printf("Child1: pid = %d - parent's pid: %d\n",getpid(),getppid()); 
     } 
    } 

    child2=fork(); 
    if(child2<0) { perror("fork"); exit(errno);} 
    if(child2==0){ 
     while(1){ 
      sleep(5); 
      printf("Child2: pid = %d - parent's pid: %d\n",getpid(),getppid()); 
     } 
    } 

    child3=fork(); 
    if(child3<0) { perror("fork"); exit(errno);} 
    if(child3==0){ 
     while(1){ 
      sleep(6); 
      printf("Child3: pid = %d - parent's pid: %d\n",getpid(),getppid()); 
      printf("Sending user signal\n"); 
      if(kill(getppid(), SIGUSR1)==-1) 
       perror("Did not kill (5)");//kills child3 
       printf("user signal sent\n"); 
     } 
    } 

    printf("pid of father of all: %d\n",getpid()); 
    printf("The father %d is waiting to all children die to too\n",getpid()); 
    while(wait(NULL)!=-1); 
    printf("The father %d is going to die\n",getpid()); 
    exit(0); 
}