有一个多平台(Windows,Linux,Cygwin)动态库,在运行时由Cygwin可执行文件加载。在正常工作流程中的某个时间点,DLL会分配一个线程池供使用。这些线程作为全局变量(引用计数)进行管理。因此,当客户端进程关闭时,它开始释放全局对象,也应该释放线程。
据我所知,问题是在进程关闭期间,获取了Loader锁,然后在大街上走了,线程想要获得相同的锁,而现在我们有了死锁。
现在我要请教的是,我们怎样才能使系统关机?
DLL没有要调用的init()
或uninit()
方法。最多可以在main ()
结束之前使用一些代码来增强客户端(因此这是在进程关闭之前)。
如果在全局var清理期间分离线程而不是加入线程,则内存将损坏。如果我终止它们,那么我们的进程转储会很丑。
顺便说一句,在Linux下我看不到这样的问题。
DLL仅是C ++ 14,客户端是C99(Cygwin)。
我试图弄清楚情况,但是如果您还有其他问题,请告诉我。预先感谢您的任何想法。
答案 0 :(得分:0)
解决方法是向DLL添加uninit
方法。它可能还没有,但需要一个。您发现了原因:虽然操作系统将在DLL卸载时调用DllMain
,但它在加载器锁定下进行了调用。您需要执行在加载程序锁定下无法执行的操作,因此您需要在DllMain
之前进行额外的调用。为该方法uninit()
命名足够合理。
C ++ 14在这里不是问题;这是一种操作系统机制。装载机锁自古以来就存在。
答案 1 :(得分:0)
在上一份工作中,我在这个问题上苦苦挣扎了很长时间。最终,它只能归结为两种可能的解决方案:
作为补充说明,我还学会了不惜一切代价避免将任何全局变量链接到DLL的生命周期。这些将在DllMain上下文中执行其构造函数和析构函数,不用多说...如果您需要DLL中的全局单例,请确保对其生命周期进行手动控制(在两端,因此没有自动破坏智能指针)要么。)