自动测试后安全清理阻塞的 std::thread

Posted

技术标签:

【中文标题】自动测试后安全清理阻塞的 std::thread【英文标题】:Safely cleaning up a blocking std::thread after an automated test 【发布时间】:2016-01-18 13:05:12 【问题描述】:

考虑一些 Mutex 类实现的测试用例。测试在执行期间创建了几个 std::thread 实例。如果根据测试正确实现了 Mutex 类,则所有线程都应该完成。如果出现问题,一个线程可能会无限期地阻塞。测试后如何正确清理?

一开始还想拆线,结果线泄露了。更糟糕的是,线程依赖于测试用例内部的 Mutex 实例,这会在测试用例返回后偶尔导致访问冲突。 一些线程库,例如 Qt 的 QThread 有 terminate() 方法,但我想使用 std::thread 即使 Qt 已经是我项目的依赖项。

是否存在用于测试可能无限期阻塞的并发代码的通用模式?

【问题讨论】:

【参考方案1】:

杀死可能持有锁的线程是不赞成强制终止线程的主要原因之一,也是 C++11 不支持它的主要原因之一。你不应该这样做,期间。

如果您需要做类似的事情,最好的办法可能是生成一个新进程来运行测试;如果它被锁定,您可以终止进程而不会产生同样的风险。

有关为什么终止线程是坏消息的示例,请查看specific example from the Old New Thing on what sort of garbage thread termination leaves lying around on Windows;在不同的环境下,大多数操作系统都会出现类似的问题。

【讨论】:

【参考方案2】:

我认为析构函数可以在这里提供帮助,这是唯一 100% 确定在任何问题后执行的东西,这是设计上的。我建议在一些析构函数内部进行一个很好的阻塞测试,并在离开之前以安全的方式(智能指针?)释放资源。

【讨论】:

析构函数如何包装测试方法来解决问题?如果 std::thread 实例的析构函数在这个包装析构函数中运行,您仍然会遇到销毁正在运行的 std::thread 的问题,这会导致整个应用程序被终止(崩溃)。 我没有考虑线程实例的析构函数,可能是任何可以访问线程处理程序的析构函数(在最坏的情况下考虑),这个问题的解决方案是收敛的(在 90% 的实现中我已经看到)使用专用进程来检查线程中的问题作为之前的 ShadowRanger 注释,并且可以使用该析构函数进行此测试,特别是在析构函数中不运行进程。 ***.com/questions/29178435/…检查这个,不一样,但会有所帮助。

以上是关于自动测试后安全清理阻塞的 std::thread的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::thread 阻塞执行?

std::thread::join 无限期地阻塞在 main 之外

继承std::thread时如何安全调用成员函数

在类构造函数线程中启动 std::thread 是不是安全?

如何安全地删除 ATL DLL 中的 std::thread

std::thread.join() 做啥?