簡體   English   中英

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

[英]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被多次調用。
例:

  1. 服務器正在監聽;
  2. 2 x收到連接;
  3. 2個兒童叉子;
  4. 2個孩子被關閉;
  5. 現在我想關閉服務器,所以我按CTRL + C;

預期輸出:
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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM