簡體   English   中英

服務器中的父進程卡在接受呼叫中。 如何從孩子那里干凈地終止父母

[英]Parent process in server stuck in accept call. How do I terminate the parent cleanly from child

你好初學C程序員。

我有一個簡單的服務器客戶端設置。 我只希望一個客戶端連接到服務器,但我希望其他客戶端能夠嘗試獲取服務器被占用的消息。

我能夠通過一個客戶端連接到服務器,並讓其他嘗試連接的客戶知道沒有空間。 當客戶端告訴服務器關閉時,我的問題出現了。 子進程能夠突破循環並終止。 但是,父節點無法使用管道從子節點接收消息,因為它一直處於accept

我可以使用kill(2)來結束父節點,但是我會在關閉套接字和文件后得到一個干凈的終止嗎?

我也嘗試讓父母不要停止接受使用fcntl(sock_desc, F_SETFL, fcntl(sock_desc, F_GETFL, 0) | O_NONBLOCK); 但這開辟了新的問題。

我想以某種方式讓孩子告訴父母跳過accept行並繼續,以便它獲取管道消息並退出循環。

如果這是終止服務器的壞方法,我將不勝感激。

簡化的服務器代碼:

void termination_handler (int signum)
{
    if(signum == SIGTERM){
        //Is this where the accept call is changed?
    }
}


void main(){
struct sigaction sa = {0}; //2b) Initialise the struct sigaction variable to all 0s beforehand.   
sa.handler = termination_handler; //2a) Set the member for handler (to the signal-handler function)

sigaction(SIGTERM, &sa, NULL);    

pid_t pid; 
int loop = 1;
while(loop){
    int sock = accept(net_sock, NULL, NULL); //After connection 
                                             //parent is stuck here

    if(kill(pid,0) == -1){
        pid = fork();
    }
    else{
         //Tell second client there is no room and close socket
    }

    //Child
    if(pid == 0){
        while(loop){ 
            //Read signal in from client to end child loop and terminate child
            //Write with pipe to parent to end parent loop and terminate parent
            kill(getppid(), SIGTERM) // Is this how I do it?
        }
    }
    //Parent
    else{ 
        close(sock);
        //Read with pipe from child to end loop   
        //After first connection, the parent won't get this message
    }
}

操作系統將為您關閉文件描述符。 除非您有其他清理工作要做(例如寫入文件或刪除某些文件),否則使用未處理的終止信號(例如, SIGTERMSIGINT )進行終止就足夠了。

如果你還有其他清理工作要做,請讓孩子用父母信號處理器建立一個信號的父母信號(你需要用sigaction建立處理程序)。 這將使用返回碼-1errno == EINTR打破accept ,允許您做任何您需要做的事情。

volatile sig_atomic_t usr1 = 0;
void usr1_handler(int Sig) { usr1 = 1; }
//...
int main() {  //...
   sigaction(SIGUSR1, &(struct sigaction){.sa_handler=usr1_handler},0);
   //...
   usr1 = 0;
   sock =  accept( /*... */ );
   if ( -1 == sock && EINTR == errno && usr1 ) //was interrupted by USR1
      /* cleanup and exit */;

讓孩子在結束之前發信號通知它的父母。 如果正確完成, accept()將返回信號接收,返回-1並將errnoEINTR

來自accept()的文檔

返回值

成功完成后, accept()將返回已接受套接字的非負文件描述符。 否則,應返回-1,設置errno以指示錯誤,[...]

[...]

錯誤

如果出現以下情況,accept()函數將失敗:

[...]

[EINTR] accept()函數被有效連接到達之前捕獲的信號中斷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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