繁体   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