简体   繁体   English

多次调用sigint,而不是一次(C)

[英]sigint called multiple times instead of one (C)

This is a snippet of my code: 这是我的代码的片段:

signal (SIGINT, ( void *)sig_handler); 

while(1){
    newsockd = -1;
    memset(&cli_addr, 0, sizeof(cli_addr));

    if((newsockd = accept(sockd, (struct sockaddr *) &cli_addr, (socklen_t *) &socket_len)) < 0){
        perror("Errore nella connessione\n");
        onexit(newsockd, sockd, 0, 2);
    }
    fprintf(stdout, "Ricevuta richiesta di connessione dall' indirizzo %s\n", inet_ntoa(cli_addr.sin_addr));

    child_pid = fork();
    if(child_pid < 0){
        perror("Fork error");
        onexit(newsockd, sockd, 0, 2);
    }
    if(child_pid == 0){
        do_child(newsockd);
        exit(0);
    }
    else{
       while(waitpid(child_pid, NULL, WNOHANG) > 0)
        continue;
       }
    }
}

and the function sig_handler: 和函数sig_handler:

void sig_handler(const int signo, const int sockd, const int newsockd){
  if (signo == SIGINT){
    printf("Received SIGINT, exiting..\n");
    if(newsockd) close(newsockd);
    if(sockd) close(sockd);
    exit(EXIT_SUCCESS);
  }
}

The problem happens when i press "CTRL+C" because sighandler is called multiple times. 当我按“ CTRL + C”时会发生问题,因为sighandler被多次调用。
Example: 例:

  1. Server is listening; 服务器正在监听;
  2. 2 x Connection received; 2 x收到连接;
  3. 2 x child fork; 2个儿童叉子;
  4. 2 x child are closed; 2个孩子被关闭;
  5. now i want to close the server so i press CTRL+C; 现在我想关闭服务器,所以我按CTRL + C;

expected output: 预期输出:
received SIGINT, exiting....
real output: 实际输出:
received SIGINT, exiting....
received SIGINT, exiting....
received SIGINT, exiting....

Why i got this behaviour? 为什么我有这种行为?

EDIT: code updated 编辑:代码已更新
This is what happens when 1 fork is done and when the child has finished i close the server: 这是在完成1个分叉并且孩子完成后关闭服务器时发生的情况:

^C7518
7516
Received SIGINT, exiting...
Received SIGINT, exiting...

SOLUTION FOUND: the problem was that i haven't write exit(0) after the instruction do_child() ...code updated! 找到的解决方案:问题是指令do_child() ...代码更新后,我还没有写exit(0)

The signal is sent to every child process of the current process. 信号被发送到当前进程的每个子进程。
In your code, when you're using fork , you create a child process that inherits from the main process the SIGINT handler. 在代码中,当您使用fork ,您将创建一个从主进程继承SIGINT处理程序的子进程。 That's why the message is printed several times. 这就是为什么消息会多次打印的原因。

There are few observations, 观察很少

1)You should better use sigaction instead of signal function. 1)您最好使用sigaction代替信号功能。 http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigaction.html http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigaction.html

2)Now some fixes in your current code. 2)现在,您的当前代码已得到一些修复。 You may use 您可以使用

if(child_pid == 0)
{
   /*Now in the child make again the action for SIGINT default, so that 
   your handler does not get called.*/ 
       signal (SIGINT, SIG_DFL);
       do_child(newsockd);
}   

3)Why you are calling waitpid in the main loop? 3)为什么在主循环中调用waitpid? You should have a handler for SIGCHLD and then use wait/waitpid inside it. 您应该具有SIGCHLD的处理程序,然后在其中使用wait / waitpid。

Ideally after creating a child to serve client, the main loop should go back to accept. 理想情况下,在创建一个要为客户服务的孩子之后,主循环应返回接受状态。 (If it is geeting blocked after creation of a child then how your server becomes a concurrent server?) (如果在创建子节点后geeting被阻止,那么您的服务器如何成为并发服务器?)

(Or for the first version, I would suggest you avoid this instead use, after your call to signal handler for SIGINT, (或者,对于第一个版本,建议您在调用SIGINT的信号处理程序后避免使用此方法,

signal(SIGCHLD, SIG_IGN);  //This should  automatically get rid of zombies.

(Pl. experiment this in your system) (请在您的系统中进行实验)

Link for reference - http://en.wikipedia.org/wiki/SIGCHLD 参考链接-http: //en.wikipedia.org/wiki/SIGCHLD

4)It seems your argument to the handler for SIGINT is also not proper.The proper prototype is 4)似乎您对SIGINT的处理程序的争论也不正确。正确的原型是

void (*signal(int sig, void (*func)(int)))(int);

But your handler is 但是你的经理是

void sig_handler(const int signo, const int sockd, const int newsockd).

How the values of sockfd & newsockfd are getting passed? sockfd和newsockfd的值如何传递?
Link 链接

http://pubs.opengroup.org/onlinepubs/009696899/functions/signal.html http://pubs.opengroup.org/onlinepubs/009696899/functions/signal.html

I am not sure how you kill the child process.If the child process is not in Zomb status yet, your sign_handler will work on it. 我不确定您如何杀死子进程。如果该子进程尚未处于Zomb状态,则您的sign_handler将对其进行处理。 May need add more log to clarify the sequence of child process life cycles. 可能需要添加更多日志以阐明子进程生命周期的顺序。

On a related note: I found that I was getting multiple SIGINT for a single CTRL+C as well. 在相关说明中:我发现我也为单个CTRL + C获得了多个SIGINT。 When I checked my task manager, I actually had multiple hung node.js scripts for this application. 当我检查任务管理器时,实际上该应用程序有多个挂起的node.js脚本。 Once I terminated them in task manager, I started receiving single SIGINT as expected. 在任务管理器中终止它们后,我开始按预期接收单个SIGINT。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM