我正在编写一个具有永久循环的小型服务器,并且希望能够正确停止它,例如在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/