【发布时间】:2015-01-06 00:24:14
【问题描述】:
有没有摆脱无限循环的好方法? (我尝试捕获一个 SIGINT,但它不会让我在退出前清理)
我正在做一个客户端-服务器。 每次客户端连接时,服务器分叉并为客户端指定一个子节点(该子节点会将标准输入和标准输出重定向到 fifo 或套接字的 fd,然后执行) 在服务器中,我目前正在无限循环中监听客户端
for(;;)
{
listen_client();
create_child();
}
(或多或少) 该应用程序运行良好(每个客户端都可以与其指定的子服务器完美通信)。 问题出在服务器关闭上。
我想知道是否有关闭服务器的好方法(我不习惯使用无限循环,不确定它是否正确,也不确定是否有好的方法)。
我尝试了一个 sig_handler (sigaction),但我似乎无法让它工作(理想情况下,我会在退出之前关闭所有 fd、杀死所有子进程并删除所有 fifo)。
编辑
使用一个全局变量来跟踪孩子并在 sig_handler() 中进行修改,它似乎正在工作,但仍然不确定这是一个好方法
(sig 处理程序中的代码)
while(childs > 0)
{
pid = wait(NULL);
//cleanup mess of child
childs--
}
我的疑问是: 孩子总是自动死亡吗?或者我应该发送一个杀戮或其他东西(在这种情况下,我猜我需要跟踪每个pid)。 有制造僵尸的风险吗? 是否有进入死循环的风险? (除了这里,我从不减少“孩子”,我不确定等待是否也包括很久以前死去的孩子)。
我知道这“行得通”,但我宁愿学习以“正确”的方式去做(如果有的话)
【问题讨论】:
-
break;问题出在哪里? -
问题是我如何确定在哪里休息。我希望循环是“无限的”(只要它运行就继续监听客户端),我想要的是让它死干净
-
将无限循环修改为
while (termsig_received == 0) { ... },并让信号处理程序将声明为static volatile sig_atomic_t termsig_received = 0;的变量设置为1,然后在循环结束后,清理您的心。您可以在 Linux 上的信号处理程序中做的事情比根据标准 C 做的更多,但通常最好避免在信号处理程序中做太多事情,设置标志和测试是一种很好的方法。您可能需要修改listen_client()代码以返回一个值,例如,如果要创建一个孩子,则返回 0,如果它被中断,则返回 -1。 -
这是否适用于 SIGINT?如果我遵循正确,sig 只会更改变量,它究竟会如何影响进程(进程在哪里恢复?)它不会仍然被listen_client()阻塞吗?例如,如果 listen_client() 正在等待客户端打开 fifo(或写入,或任何会产生阻塞的东西),并且发生了 sigaction,它返回时不会继续被阻塞吗?
-
代码可以使用'atexit()'函数来参数atexit是一个函数名。该函数会完成所有清理工作。
标签: c client-server parent-child infinite-loop exit