【问题标题】:What is wrong with sending signal after fork in below code在下面的代码中分叉后发送信号有什么问题
【发布时间】:2019-09-23 10:16:58
【问题描述】:

我编写了以下代码:在 fork() 函数之后,父级向子级发送信号。我认为孩子收到信号并终止。 我不想要这个解决方案,因为我可以通过以下两种方式解决它。 我想知道这个问题的原因是什么?

我最初尝试的代码如下:

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

#define maxchild 1

int inchild=-1;

void sighandler(int signo){
    char buffer[256];
    int a,b=0;
    switch(signo){
    case SIGUSR1:
        printf("SIGUSR1\n");
        break;
    case SIGUSR2:
        printf("SIGUSR2\n");
        break;
}
}


int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
    ids[i]=fork();
    printf("here %d\n",ids[i]);
    if(ids[i]==0){
        printf("in child\n");
        inchild=i+1;
        break;
    }
}
while(inchild>=0) {
}
//  sleep(1);
if(inchild==-1){
    for(int i=0;i<maxchild;i++){
        printf("child: %d\n parent: %d\n",ids[i],getpid());
        kill(ids[i],SIGUSR1);
    }

}
  if (inchild==-1) wait(NULL);
    return 0;
}

当我多次运行代码时,我希望每次都能在输出中看到“SIGUSR1”,但大多数输出​​是:

here 17573 (or any other positive number)
child: 17573
parent: 17572

然后程序突然终止。 我知道我可以通过两种解决方案来解决它: 1. fork() 函数后父母最常睡觉:

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

#define maxchild 1

int inchild=-1;

void sighandler(int signo){
    char buffer[256];
    int a,b=0;
    switch(signo){
    case SIGUSR1:
        printf("SIGUSR1\n");
        break;
    case SIGUSR2:
        printf("SIGUSR2\n");
        break;
}
}


int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
    ids[i]=fork();
    printf("here %d\n",ids[i]);
    if(ids[i]==0){
        printf("in child\n");
        inchild=i+1;
        break;
    }
}
while(inchild>=0) {
}
    sleep(1);
if(inchild==-1){
    for(int i=0;i<maxchild;i++){
        printf("child: %d\n parent: %d\n",ids[i],getpid());
        kill(ids[i],SIGUSR1);
    }

}
  if (inchild==-1) wait(NULL);
    return 0;
}

它会正常工作

  1. 我也可以评论“kill(...)”行来解决问题:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/time.h>
    #include <wait.h>
    #include <time.h>
    #include <unistd.h>
    #include <signal.h>
    
    #define maxchild 1
    
    int inchild=-1;
    
    void sighandler(int signo){
    char buffer[256];
    int a,b=0;
    switch(signo){
    case SIGUSR1:
        printf("SIGUSR1\n");
        break;
    case SIGUSR2:
        printf("SIGUSR2\n");
        break;
    }
    }
    
    
    int main(){
    pid_t ids[maxchild];
    struct sigaction control;
    control.sa_flags=0;
    control.sa_handler=sighandler;
    sigemptyset(&control.sa_mask);
    sigaction(SIGUSR1,&control,NULL);
    sigaction(SIGUSR2,&control,NULL);
    for(int i=0;i<maxchild;i++){
        ids[i]=fork();
        printf("here %d\n",ids[i]);
        if(ids[i]==0){
            printf("in child\n");
            inchild=i+1;
            break;
        }
    }
    while(inchild>=0) {
    }
     //      sleep(1);
    if(inchild==-1){
        for(int i=0;i<maxchild;i++){
            printf("child: %d\n parent: %d\n",ids[i],getpid());
        //  kill(ids[i],SIGUSR1);
        }
    
    }
      if (inchild==-1) wait(NULL);
        return 0;
    }
    

    现在我想知道问题的原因。

我想运行第一个代码并查看: 这里(正数) 这里 0 在孩子 孩子:(一个正数) 父母:(正数) SIGUSR1 并且程序必须继续运行,直到我按下 Ctrl+c (当然输出中的行顺序无关紧要)

我不想更改代码,我想知道问题的原因。 提前谢谢你

【问题讨论】:

  • 对于初学者,请初始化您正确使用的变量:将所有 struct sigaction control; 更改为 struct sigaction control = {0};
  • 此外,如果您希望父母只要至少有一个孩子还活着,就让它呼叫wait() 的次数与分叉孩子的次数一样多。
  • 在信号处理程序中调用非异步安全函数的未定义行为。
  • @EOF 我没有在信号处理程序中调用任何函数!另一方面,如果我只添加一个睡眠就可以了。所以处理程序不是问题的原因。
  • @milad 您正在使用printf(),它不在安全列表中:man7.org/linux/man-pages/man7/signal-safety.7.html

标签: c linux signals fork kill


【解决方案1】:

如果进程安装了信号处理程序,则会在接收到信号时调用它。这个过程还没有结束。所以所有的孩子都被困在了

  while (inchild >= 0) {
  } 

由于没有孩子结束,父母正在阻止wait()

要解决这个问题,请将上面的 sn-p 替换为

  if (inchild >= 0) {
    pause();
  }

【讨论】:

  • 谢谢,但问题出在信号处理程序中。我不会在信号处理程序中调用 printf()
  • @milad 只是 only 从信号处理程序中删除 printfs 解决了您的问题吗?示例 1 没有 printfs 不会阻塞父级?我对此表示怀疑。
猜你喜欢
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-12
相关资源
最近更新 更多