简体   繁体   English

服务器中的父进程卡在接受呼叫中。 如何从孩子那里干净地终止父母

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

Hello from a beginner C programmer. 你好初学C程序员。

I have a simple server client setup. 我有一个简单的服务器客户端设置。 I only want one client to connect to the server, but I want other clients to be able to try and get a message that the server is occupied. 我只希望一个客户端连接到服务器,但我希望其他客户端能够尝试获取服务器被占用的消息。

I am able to connect to the server with one client, and let other clients trying to connect know there is no room. 我能够通过一个客户端连接到服务器,并让其他尝试连接的客户知道没有空间。 My problem occurs when the client tells the server to shut down. 当客户端告诉服务器关闭时,我的问题出现了。 The child process is able to break out of the loops and terminate. 子进程能够突破循环并终止。 The parent, however, is not able to receive the message from the child using pipe, because it is stuck on accept . 但是,父节点无法使用管道从子节点接收消息,因为它一直处于accept

I could use kill(2) to end the parent, but will I get a clean termination with closing of sockets and files then? 我可以使用kill(2)来结束父节点,但是我会在关闭套接字和文件后得到一个干净的终止吗?

I have also tried to let the parent not stop at accept using fcntl(sock_desc, F_SETFL, fcntl(sock_desc, F_GETFL, 0) | O_NONBLOCK); 我也尝试让父母不要停止接受使用fcntl(sock_desc, F_SETFL, fcntl(sock_desc, F_GETFL, 0) | O_NONBLOCK); but this opens up new problems. 但这开辟了新的问题。

I want to somehow make the child tell the parent to skip the accept line and continue so that it gets the pipe message and exits the loop. 我想以某种方式让孩子告诉父母跳过accept行并继续,以便它获取管道消息并退出循环。

If this is a bad way to terminate servers I would appreciate to learn about that. 如果这是终止服务器的坏方法,我将不胜感激。

Simplified server code: 简化的服务器代码:

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
    }
}

The OS will close filedescriptors for you. 操作系统将为您关闭文件描述符。 Unless you have other cleanup work to do (such as writing into files or removing some files), a kill with an unhandled terminating signal (eg, SIGTERM or SIGINT ) should be sufficient. 除非您有其他清理工作要做(例如写入文件或删除某些文件),否则使用未处理的终止信号(例如, SIGTERMSIGINT )进行终止就足够了。

If you do have other cleanup work to do, have the child signal the parent with a signal for which the parent has a signal handler established (you need to establish the handler with sigaction ). 如果你还有其他清理工作要做,请让孩子用父母信号处理器建立一个信号的父母信号(你需要用sigaction建立处理程序)。 That will break accept with return code -1 and errno == EINTR , allowing you to do whatever you need to do. 这将使用返回码-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 */;

Let the child signal it's parent before ending. 让孩子在结束之前发信号通知它的父母。 If done correctly accept() returns on signal reception, returning -1 and setting errno to EINTR . 如果正确完成, accept()将返回信号接收,返回-1并将errnoEINTR

From accept() 's documentation : 来自accept()的文档

RETURN VALUE 返回值

Upon successful completion, accept() shall return the non-negative file descriptor of the accepted socket. 成功完成后, accept()将返回已接受套接字的非负文件描述符。 Otherwise, -1 shall be returned, errno shall be set to indicate the error, [...] 否则,应返回-1,设置errno以指示错误,[...]

[...] [...]

ERRORS 错误

The accept() function shall fail if: 如果出现以下情况,accept()函数将失败:

[...] [...]

[EINTR] The accept() function was interrupted by a signal that was caught before a valid connection arrived. [EINTR] accept()函数被有效连接到达之前捕获的信号中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当父进程等待子进程终止时,子进程如何杀死父进程? - How can child kill parent process while parent process waits until child process to terminate? 当我不等待父进程中的子进程时,如何终止程序? - How can I terminate the program when I am not waiting for the child process in the parent? 如何让我的父母等待,直到中间父母的中间父母、孩子和孩子使用 fork、wait 和 waitpid 完成该过程? - How do I make my parent wait, until a Intermediate parent, child and child of Intermediate parent finish the process using fork, wait, and waitpid? 如何从其父级恢复已暂停的子进程? - How can I resume a paused child process from its parent? 在C语言中,如果父进程终止,那么子进程会自动终止吗? - In C, if a parent process terminates, then will the child process automatically terminate? 在 C 语言的 Linux 编程中,子进程可以等待父进程终止吗? - Can a child process wait for the parent process to terminate in Linux programming in C? 如何将管道从父进程发送到子进程 - how to send the pipe from parent to child process 如何从父进程向孩子发出信号? - How to signal from parent process to the child? 创建子进程,让子进程的父进程传输文件。我该怎么做? - Create child process, make parent of the child to transmit a file.How do i do this? 从父级父级到子级进程的管道无法正常工作 - Piping from parent parent to child process not working
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM