我正在编写一个具有永久循环的小型服务器,并且希望能够正确停止它,例如在Ctrl + C(SIGINT)上。

class Server
{
...
public:
  void loop()
  {
    while(_run_flag)
    {
      // do something
    }
  }
  void stop()
  {
    _run_flag = 0;
  }
...
private:
  volatile sig_atomic_t _run_flag = 1;
};

namespace
{
std::function<void()> callback_wrapper;

void signal_handler(int)
{
  callback_wrapper();
}

}

int main()
{
  std::unique_ptr<WSGIServer> server = CreateServer("127.0.0.1", 4009);
  callback_wrapper = [&](){ server->stop(); };

  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = signal_handler;
  sigemptyset(&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction(SIGINT, &sigIntHandler, NULL);

  server->loop();

  return 0;
}

我有以下问题:
  • 我应该使用什么run_flag_variable类型?使用volatile sig_atomic_t可以吗?
  • stop中调用signal_handler方法安全吗?
  • 最佳答案

    似乎几乎是合法的,除非我不能提出什么改进。一个不是那么严重:如果只能使用C++,我的意思是基元形成csignal header ,并尝试避免volatile我们已经有了atomic东西,更多的您可以阅读我的答案here,认为这个问题没有太大的意义。第二,在信号处理程序中您可以做和不能做的事情有很多警告,C++-14,17发生了很大变化,除了有一些非标准的,但平台特定的做事方式,但是最简单的规则是您必须使用原子/ Volatile Material ,如果不使用,则必须有充分的理由并且是特定于平台的。

    std::atomic_bool global_run_flag(true);
    
    class Server {
    public:
      Server() : _local_run_flag(true) {}
    
      void loop() {
        while (_local_run_flag && global_run_flag) {
          // do something
        }
      }
      void stop() { _local_run_flag = false; }
    
    private:
      std::atomic_bool _local_run_flag;
    };
    
    void signal_handler(int) { global_run_flag = false; }
    
    int main() {
      std::unique_ptr<Server> server(new Server);
    
      std::signal(SIGINT, &signal_handler);
    
      server->loop();
    
      return 0;
    }
    

    我举了一个示例,说明如何跟踪信号处理程序中的全局条件集,例如,如果需要,可以跟踪其他线程中的局部条件集。

    关于c++ - 在中断信号上对服务器实现停止 Action 的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51800158/

    10-11 23:09
    查看更多