这是我的代码片段:
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;
}
}
}
和函数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);
}
}
当我按“CTRL + C”时会出现问题,因为sighandler被多次调用
例如:
预期产量:
received SIGINT, exiting....
真实输出:
received SIGINT, exiting....
received SIGINT, exiting....
received SIGINT, exiting....
为什么我有这种行为?
编辑:代码更新
当完成1个fork并且孩子完成后我关闭服务器时会发生这种情况:
^C7518
7516
Received SIGINT, exiting...
Received SIGINT, exiting...
解决方案:问题是我在指令exit(0)
...代码更新后没有写do_child()
!
答案 0 :(得分:2)
信号被发送到当前进程的每个子进程
在您的代码中,当您使用fork
时,您将创建一个子进程,该进程从主进程继承SIGINT
处理程序。这就是为什么消息被多次打印的原因。
答案 1 :(得分:2)
观察很少,
1)你最好使用sigaction代替信号功能。 http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigaction.html
2)现在有些修复你当前的代码。你可以使用
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)为什么你在主循环中调用waitpid?您应该拥有SIGCHLD的处理程序,然后在其中使用wait / waitpid。
理想情况下,在创建一个子服务器来为客户端服务之后,主循环应该回到接受状态。 (如果在创建子项后它被阻止了geeting,那么您的服务器如何成为并发服务器?)
(或者对于第一个版本,我建议你在调用SIGINT的信号处理程序之后避免使用它,
signal(SIGCHLD, SIG_IGN); //This should automatically get rid of zombies.
(Pl。在您的系统中进行实验)
参考链接 - http://en.wikipedia.org/wiki/SIGCHLD
4)似乎你对SIGINT处理程序的参数也不合适。正确的原型是
void (*signal(int sig, void (*func)(int)))(int);
但是你的处理程序是
void sig_handler(const int signo, const int sockd, const int newsockd).
sockfd&amp;的价值如何newsockfd正在通过? 链接
http://pubs.opengroup.org/onlinepubs/009696899/functions/signal.html
答案 2 :(得分:0)
我不确定你是如何杀死子进程的。如果子进程还没有处于Zomb状态,你的sign_handler将会对它进行处理。可能需要添加更多日志来阐明子进程生命周期的顺序。
答案 3 :(得分:0)
在相关的说明中:我发现我也为单个CTRL + C获得了多个SIGINT。当我检查我的任务管理器时,我实际上为此应用程序提供了多个挂起的node.js脚本。一旦我在任务管理器中终止它们,我开始按预期接收单个SIGINT。