![](/img/trans.png)
[英]How do I ensure the `SIGINT` signal handler is called as many times as `Ctrl+C` is pressed (with `longjmp`)?
[英]sigint called multiple times instead of one (C)
這是我的代碼的片段:
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個分叉並且孩子完成后關閉服務器時發生的情況:
^C7518
7516
Received SIGINT, exiting...
Received SIGINT, exiting...
找到的解決方案:問題是指令do_child()
...代碼更新后,我還沒有寫exit(0)
!
信號被發送到當前進程的每個子進程。
在代碼中,當您使用fork
,您將創建一個從主進程繼承SIGINT
處理程序的子進程。 這就是為什么消息會多次打印的原因。
觀察很少
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.
(請在您的系統中進行實驗)
參考鏈接-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和newsockfd的值如何傳遞?
鏈接
http://pubs.opengroup.org/onlinepubs/009696899/functions/signal.html
我不確定您如何殺死子進程。如果該子進程尚未處於Zomb狀態,則您的sign_handler將對其進行處理。 可能需要添加更多日志以闡明子進程生命周期的順序。
在相關說明中:我發現我也為單個CTRL + C獲得了多個SIGINT。 當我檢查任務管理器時,實際上該應用程序有多個掛起的node.js腳本。 在任務管理器中終止它們后,我開始按預期接收單個SIGINT。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.