【问题标题】:C - Nice way to terminateC - 终止的好方法
【发布时间】: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


【解决方案1】:

您可以禁用异步信号生成,在其上创建一个 signalfd(2) 和 poll(2)。这样您就可以正确处理所有信号并保持线性程序流,包括正确的清理。 IMO 这是一个非常方便的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多