在进程关闭过程中结束DLL中的全局线程

时间:2018-11-06 11:28:14

标签: c++ windows multithreading dll c++14

有一个多平台(Windows,Linux,Cygwin)动态库,在运行时由Cygwin可执行文件加载。在正常工作流程中的某个时间点,DLL会分配一个线程池供使用。这些线程作为全局变量(引用计数)进行管理。因此,当客户端进程关闭时,它开始释放全局对象,也应该释放线程。

据我所知,问题是在进程关闭期间,获取了Loader锁,然后在大街上走了,线程想要获得相同的锁,而现在我们有了死锁。

现在我要请教的是,我们怎样才能使系统关机?

DLL没有要调用的init()uninit()方法。最多可以在main ()结束之前使用一些代码来增强客户端(因此这是在进程关闭之前)。

如果在全局var清理期间分离线程而不是加入线程,则内存将损坏。如果我终止它们,那么我们的进程转储会很丑。

顺便说一句,在Linux下我看不到这样的问题。

DLL仅是C ++ 14,客户端是C99(Cygwin)。

我试图弄清楚情况,但是如果您还有其他问题,请告诉我。预先感谢您的任何想法。

2 个答案:

答案 0 :(得分:0)

解决方法是向DLL添加uninit方法。它可能还没有,但需要一个。您发现了原因:虽然操作系统将在DLL卸载时调用DllMain,但它在加载器锁定下进行了调用。您需要执行在加载程序锁定下无法执行的操作,因此您需要在DllMain之前进行额外的调用。为该方法uninit()命名足够合理。

C ++ 14在这里不是问题;这是一种操作系统机制。装载机锁自古以来就存在。

答案 1 :(得分:0)

在上一份工作中,我在这个问题上苦苦挣扎了很长时间。最终,它只能归结为两种可能的解决方案:

  1. 清理线程拥有的每个资源,然后清理TerminateThread。这是暴力和丑陋的,但可以解决THREAD_DETACH问题,实际上我在Internet上找到了建议。
  2. 如果您有能力在PROCESS_DETACH之前提前获得通知,请在此早点清理所有内容,包括有序地关闭线程。然后,在PROCESS_DETACH期间,绝对不要执行任何操作-是的,甚至不要释放任何挥之不去的堆对象,因为您可能会使自己陷入死锁或崩溃的风险,并且该进程将关闭并释放所有资源。

作为补充说明,我还学会了不惜一切代价避免将任何全局变量链接到DLL的生命周期。这些将在DllMain上下文中执行其构造函数和析构函数,不用多说...如果您需要DLL中的全局单例,请确保对其生命周期进行手动控制(在两端,因此没有自动破坏智能指针)要么。)