2017-04-05 77 views
0

我需要发送一个信号给子进程3次。如何向儿童多次发送信号避免僵尸状态? C语言

问题是,孩子只接收信号一次,然后转化为僵尸。

预期输出是:

我孩子11385和我收到SIGUSR1

我孩子11385和我收到SIGUSR1

我孩子11385和我收到SIGUSR1

但真正的输出是:

我孩子11385和我收到SIGUSR1

#include <ctype.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

void my_handler() 
{ 
    printf("\n I'm the child %i and i received SIGUSR1\n", getpid()); 
} 


int main (int argc, char **argv) { 
    int *array; 
    int N = 10; 
    int i; 
    pid_t pid1; 
    array=(int*)malloc(sizeof(int)*N); 


    signal(SIGUSR1,my_handler); 

    for (i = 0; i< N; i++) 
    { 
     pid1 = fork(); 
     if(pid1 < 0) 
     { 
      exit(EXIT_FAILURE); 
     } 
     else if (pid1 > 0) 
     { 
      array[i]= pid1; 
     } 

     else 
     { 
      sleep(100); 
      exit(EXIT_SUCCESS); 
     } 
    } 

    i=0; 
    while(i<3) // I need to call the son 3 times 
    { 
     kill(array[1], SIGUSR1); 
     i++; 
    } 
} 
+0

'无效my_handler()' - >>'无效my_handler(INT正负号)'[使用错误的签名,从信号处理函数返回有效地杀死你的孩子]并且:您不应该在信号处理程序中调用printf()。 – wildplasser

+0

@wildplasser该代码是特定信号的示例,因此它没有参数。 printf也是一个例子,并不是真正的问题:/ –

+0

但是它被**称为带有参数的参数,它会中断堆栈(返回) – wildplasser

回答

1

当孩子收到信号时,它可能正在等待sleep终止。即使时间未到期,第一个信号也会中断sleep,导致它返回errno设为EINTR。如果您希望保持睡眠状态,则需要再次拨打sleep

+0

我添加了一个睡眠,并显示消息两次,如果我添加4它显示了4次,我怎么办N睡眠 无论如何,那些睡眠阻止我杀死进程,所以SIGTERM信号不起作用 –

+0

把睡眠放在一个循环中,你的SIGTERM处理程序应该设置一个全局变量,表示循环应该终止(变量应该是volatile) – rici

+0

或者检查sleep的返回值,它返回一个值有一个原因,实际上,这个用例非常多。 –

1
  • 你的父进程退出没有wait()就为孩子
  • 的信号可以被发送到快,我加了一个短暂的延迟
  • 我加入了更多的延迟
  • 正确签名的信号处理程序是void handler(int signum)这是至关重要的,因为处理程序是通过参数调用的,并且信号处理程序的堆栈布局不同。
  • 您不应该从信号处理程序调用printf(),它不是异步安全的。

#include <ctype.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <signal.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/wait.h> 

char pidstr[10]; 
char massage[]="  I'm the child and i received SIGUSR1\n"; 

#define CNT 1 
void my_handler(int signum) 
{ 
write(0, massage, strlen(massage)); 
} 


int main (int argc, char **argv) { 
    int i , err, status; 
    pid_t pid1; 
    int array[CNT]; 

    signal(SIGUSR1, my_handler); 

    for (i = 0; i< CNT; i++) { 
     pid1 = fork(); 
     if(pid1 < 0) { exit(EXIT_FAILURE); } 
     else if (pid1 > 0) { 
       printf("ChildPid=%d\n", pid1); 
      array[i]= pid1; 
     } 

     else 
     { // child 
       // signal(SIGUSR1, my_handler); 
      sprintf(pidstr,"[%d]", getpid()); 
      memcpy (massage,pidstr, strlen(pidstr)); 
      sleep(10); 
       printf("Unslept\n"); 
      sleep(10); 
       printf("Unslept\n"); 
      sleep(10); 
       printf("Unslept\n"); 
      exit(EXIT_SUCCESS); 
     } 
    } 
    sleep(10); 
    for (i=0; i<3; i++) { 
     err = kill(array[0], SIGUSR1); 
     printf("Err=%d:%d\n", err, (err) ? errno: 0); 
     sleep(1); 
    } 

    while ((pid1=wait(&status)) != -1){ 
     printf("[Parent] Reaped %d\n", pid1); 
     } 

return 0; 
}