[英]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. 除非您有其他清理工作要做(例如写入文件或删除某些文件),否则使用未处理的终止信号(例如,
SIGTERM
或SIGINT
)进行终止就足够了。
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. 这将使用返回码
-1
和errno == 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
并将errno
为EINTR
。
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.