接收SIGINT操作时,关闭多线程c ++应用程序

时间:2018-04-29 17:18:51

标签: c++ signals

我正在使用套接字制作多线程c ++应用程序 换句话说,我有很多要关闭的对象(例如我的服务器套接字,关闭我的线程等)。

我通常从main()函数的末尾关闭所有内容但是当我的app用户按 Ctrl + C <时,我无法以合适的方式关闭所有内容/ p>

顺便说一下,我可以将我的所有实例都保存为static并关闭它们在静态函数中处理SIGINT信号,但这对我来说听起来不太合适,因为我有很多实例靠近..

我准备用sigaction或signal捕获我的所有实例,但它无法编译。

signal(SIGINT, [myInstance](int) { myInstance.close() };

确实,向匿名函数添加一个实例捕获更改签名并使其不再是函数..

还有其他合适的方式来做我正在寻找的事情吗?

3 个答案:

答案 0 :(得分:1)

使用事件驱动核心编写程序。

这个事件驱动的核心通常花费时间无所事事,等待新事件。

当您收到SIGINT时,只需与事件驱动的核心通信即信号已到达。然后让它干净地关闭并退出主。

答案 1 :(得分:1)

我假设您使用的是Linux(或其他POSIX系统)。

然后仔细阅读signal(7)signal-safety(7)pthreads(7)(在Linux C ++ 11上std::thread - s在pthreads上实现)。另请阅读POSIX signal concepts和一些Pthread tutorial

请注意,信号和线程不能很好地协同工作。

一个众所周知的技巧是在初始化时设置一些pipe(7)(自我),并在该管道上设置信号处理程序write(2),然后让你的event loop处理管道输入和poll(2) - 它。即使Qt在Calling Qt Functions From Unix Signal Handlers页面中也建议并解释了这一点。

您可能想要使用sigaction(2)(而非signal(2))并且需要提供原始函数(不是std::function或lambda表达式) - 最好是extern "C"一个(以确保编译器正在为您的信号处理程序使用C调用约定。)

您可以考虑(针对SIGINT&amp; SIGTERM)使用特定于Linux的signalfd(2)

您可能更愿意避免处理信号并使用其他inter-process communication工具(可能JSONRPC以上socket(7),或者HTTP使用某些HTTP服务器库,如{{ 3}}或libonion并使您的申请成为Wt),让您的程序轻轻终止。

答案 2 :(得分:0)

首先,看看boost :: asio,如果你还没有。这是一个很棒的图书馆,使网络变得更加容易。 至于你的问题:面向对象的设计可能对你有很大的帮助。不要直接使用套接字API。但是,如果没有任何更具体的信息(示例,片段)您的应用程序或您的背景,很难推荐任何具体的。以下是一些想法:

捕获SIGINT然后终止应用程序与主函数中等待按键的while循环没有多大区别。这只是结束应用程序的另一种方式。

编写服务器类。写一个连接类。在堆上实例化新连接并使用shared_ptr(使用make_shared)。保留活动连接对象的列表。为服务器类编写一个shutdown方法,迭代这些对象并关闭它们。在main中为每个侦听套接字实例化一个服务器对象(这样您就可以轻松拥有双栈应用程序,在IP4套接字上侦听IP4和另一个)。每个服务器都有一个单独的线程,每个连接都有一个线程(警告:当你同时有数百或数千个活动连接时这很慢)。

研究boost :: asio示例。有一些很好的例子可以做你想要的。另外,boost :: asio可以作为一个&#34;事件驱动的核心&#34;,正如另一个答案正确建议的那样。

尽可能使用RAII(资源获取是初始化)。

当您捕获SIGINT时,只需调用server :: shutdown。