如何处理control-C事件或停止我的boost :: asio服务器。我有一个tcp& udp组合服务器,并希望能够在按ctrl-c时干净利落地退出。我得到了未处理控件-C的第一次机会异常。这是我的代码
void startTCP()
{
http::syncServer::server serv( 2);
// Set console control handler to allow server to be stopped.
// console_ctrl_function = boost::bind(&http::syncServer::server::stop, &serv);
//SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
// Run the server until stopped.
serv.run();
}
void startUDP()
{
boost::asio::io_service io_service;
http::syncServer::udp_server server(io_service);
// console_ctrl_function = boost::bind(&http::syncServer::udp_server::stop, &server);
// SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
io_service.run();
}
int main(int argc, char* argv[])
{
try
{
boost::shared_ptr<boost::thread> tcpThread( new boost::thread(startTCP));
boost::shared_ptr<boost::thread> udpThread (new boost::thread(startUDP));
/*console_ctrl_function = boost::bind(&http::syncServer::udp_server::stop, &server);
SetConsoleCtrlHandler(console_ctrl_handler, FALSE);*/
tcpThread->join();
udpThread->join();
}
catch (std::exception& e)
{
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}
答案 0 :(得分:5)
从升级版1.47开始,您可以使用asio中的signal_set:
class Server {
public:
Server(...) {
_signals.add(SIGINT);
_signals.add(SIGTERM);
_signals.async_wait(bind(&Server::handle_stop, this));
}
void handle_stop() {
// do what you need to kill the Server - usually you just have to cancel all waits (incl deadline_timers), which will make the io_service exit gracefully
}
private:
boost::asio::signal_set _signals;
};
小心,提升版本,例如最新的Ubuntu是1.46 - 所以这是最前沿的(primo 2012)。
干杯,
迈克尔
答案 1 :(得分:4)
C标准库包含<signal.h>
(例如see here),您可以使用它为SIGINT注册信号处理程序(Ctrl-C)。假设您的平台支持信号,那应该可以解决问题。
您可能还想为SIGTERM注册一个处理程序,以便优雅地响应kill(1)ed。
#include <signal.h> // or <csignal> in C++
void ctrlchandler(int) { /*...*/ WE_MUST_STOP = 1; }
void killhandler(int) { /*...*/ WE_MUST_STOP = 2; }
int WE_MUST_STOP = 0;
int main() {
signal(SIGINT, ctrlchandler);
signal(SIGTERM, killhandler);
/* ... */
// e.g. main loop like this:
while(pump_loop() && 0 == WE_MUST_STOP) { }
}
正如Sam Miller所建议的那样,假设你的主循环是一个带有一些m_io_service.run()
的单线程boost.asio循环。然后代替全局标志(假设m_io_service
可见)post来自信号处理程序内的io服务的停止处理程序。
答案 2 :(得分:0)
您可以使用asio中的signal_set,就像这样
// stop on ctrlC signal
boost::asio::signal_set signals(
io_service,
SIGINT,
SIGTERM );
signals.async_wait(
boost::bind(
&boost::asio::io_service::stop,
&io_service));