c++ - 通过安装信号处理程序关闭多线程应用程序
问题描述
在下面的代码中,我创建了一个玩具类,它有一个线程写入队列,而另一个线程从该队列读取并将其打印到stdout
. 现在,为了彻底关闭系统,我为SIGINT
. 我期待信号处理程序设置std::atomic<bool>
变量stopFlag
,这将导致threadB
将毒丸(哨兵)推到遇到的队列中,该队列threadA
将停止。
class TestClass
{
public:
TestClass();
~TestClass();
void shutDown();
TestClass(const TestClass&) = delete;
TestClass& operator=(const TestClass&) = delete;
private:
void init();
void postResults();
std::string getResult();
void processResults();
std::atomic<bool> stopFlag;
std::mutex outQueueMutex;
std::condition_variable outQueueConditionVariable;
std::queue<std::string> outQueue;
std::unique_ptr<std::thread> threadA;
std::unique_ptr<std::thread> threadB;
};
void TestClass::init()
{
threadA = std::make_unique<std::thread>(&TestClass::processResults, std::ref(*this));
threadB = std::make_unique<std::thread>(&TestClass::postResults, std::ref(*this));
}
TestClass::TestClass():
stopFlag(false)
{
init();
}
TestClass::~TestClass()
{
threadB->join();
}
void TestClass::postResults()
{
while(true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::string name = "ABCDEF";
{
std::unique_lock<std::mutex> lock(outQueueMutex);
outQueue.push(name);
outQueueConditionVariable.notify_one();
}
if(stopFlag)
{
/*For shutting down output thread*/
auto poisonPill = std::string();
{
std::unique_lock<std::mutex> lock(outQueueMutex);
outQueue.push(poisonPill);
outQueueConditionVariable.notify_one();
}
threadA->join();
break;
}
}
}
void TestClass::shutDown()
{
stopFlag = true;
}
std::string TestClass::getResult()
{
std::string result;
{
std::unique_lock<std::mutex> lock(outQueueMutex);
while(outQueue.empty())
{
outQueueConditionVariable.wait(lock);
}
result= outQueue.front();
outQueue.pop();
}
return result;
}
void TestClass::processResults()
{
while(true)
{
const auto result = getResult();
if(result.empty())
{
break;
}
std::cout << result << std::endl;
}
}
static void sigIntHandler(std::shared_ptr<TestClass> t, int)
{
t->shutDown();
}
static std::function<void(int)> handler;
int main()
{
auto testClass = std::make_shared<TestClass>();
handler = std::bind(sigIntHandler, testClass, std::placeholders::_1);
std::signal(SIGINT, [](int n){ handler(n);});
return 0;
}
我使用 gcc 5.2 使用 -std=c++14 标志编译了这个。在我的 CentOS 7 机器上按 Ctrl-C 时,我收到以下错误,
terminate called after throwing an instance of 'std::system_error'
what(): Invalid argument
Aborted (core dumped)
请帮助我了解发生了什么。
解决方案
SIGINT
在您的平台上,当真正的信号到来时会调用此信号处理程序。可以在此信号处理程序内部调用的函数列表相当有限,调用其他任何函数都会导致未定义的行为。
推荐阅读
- hyperledger-fabric - 我想构建一个 Hyperledger Fabric 网络,在多个组织的多个主机上运行
- java - 如何将临时授予的 ContentProvider 权限传递给 Service?
- c# - 登录网站并使用 Html Agility Pack 设置用户代理
- swift - 如何使用枚举创建计算函数?
- docker - Dockerfile 的第一行 - 什么操作系统?
- authorization - 为动态角色和属性建模 XACML 策略
- kubernetes - Traefik 入口不适用于集群 IP
- ionic-framework - 如何将我的 Ionic 4 应用程序升级到最新的 Ionic 版本?
- css - 如何使用来自其父级的 ::after 的通用兄弟选择器
- r - 使用 NA 删除行和列但保留 R 中的值