【问题标题】:Is it ok to wait in DllMain (PROCESS_DETATCH) as long as its not forever?只要不是永远,就可以在 DllMain (PROCESS DETACH) 中等待吗?
【发布时间】:2013-01-05 09:40:13
【问题描述】:

我正在编写一个通过 USB 与硬件通信的接口 Dll。为了完全满足硬件的时序要求(防止它在没有操作消息的情况下超时等),只要我的“Open()”方法被调用,我就会为每个延迟初始化创建一个工作线程。当我的“close()”方法被调用时,我设置了一个名为“terminate”的事件,该事件由工作线程监视并等待工作线程终止。终止最多需要几百毫秒,因为需要与硬件交换一些消息。

到目前为止一切顺利,唯一的问题是当程序卸载 Dll 而不调用我的“Close()”方法时...我通过在 DllMain (PROCESS_DETATCH) 中设置“终止”事件解决了这个问题,我很漂亮当然,我可以这样做并且仍然可以填写最佳实践。唯一的问题是,如果 Dll 在没有调用 close 的情况下被卸载,但在旧工作线程终止之前再次重新加载,我会导致加载我的 Dll 的进程超时,因为我正在等待旧工作线程完成。

所以这是我的问题:如果我仅在工作线程存在且正在卸载时(通过freeLibrary) 而不是当我的整个进程被终止时,我通过查看 lpvReserved 参数进行测试?

另外:有没有更好的方法来解决我的问题?

【问题讨论】:

  • 我不确定,如果这是对您问题的回答,但至少是相关的:blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
  • 我希望你不是在等待线程退出?因为这不能在 DllMain 中完成。
  • 你能要求程序在卸载你的库之前必须调用 Close() 吗?
  • @MarcSherman 这确实是一个要求,只是我无法控制加载我的 DLL 的程序,而且它似乎并不关心我的要求
  • @Sergius 是的,除此之外,我正在等待一个线程完成......有什么解决方法?

标签: c++ multithreading winapi dll


【解决方案1】:

唯一会发生的事情是让调用 FreeLibrary 的线程(FreeLibrary 不是异步的,它等待返回值)等待你的模块正在卸载。

我已经制作了一些 DLL,有时甚至在 DLLMain 附加/分离中像 while(!IsDebuggerAttached()){} 这样的循环,并且我测试的程序的行为就像他们需要的那样。

至于其他问题解决方案:除了具有相同功能的 DLLMain attach/detach 之外,您为什么还需要其他任何东西?

【讨论】:

  • 我在某处读到,当调用 DllMain (PROCESS_DETATCH) 时,某些全局数据可能已损坏,或者某些内容可能已经被卸载。我对这个主题还不是很了解。这可能是个问题吗?什么时候会发生?
  • >在卸载库模块之前,系统通过调用模块的 DllMain 函数(如果有的话)使用 DLL_PROCESS_DETACH 值使模块与进程分离。这样做使库模块有机会清理代表当前进程分配的资源。入口函数返回后,将库模块从当前进程的地址空间中移除。
  • 来自 winapi 页面,调用 FreeLibrary 的唯一*不安全方式是来自 DLLMain.. *在单线程环境中
  • 但请阅读:|||使用 GetModuleHandle 返回的句柄调用 FreeLibrary 时要小心。 GetModuleHandle 函数不会增加模块的引用计数,因此将此句柄传递给 FreeLibrary 会导致模块过早卸载。|||但这可能不会影响您,或者是吗?
【解决方案2】:

我在我的 PROCESS_DETACH 中实现了一个等待,它起初可以工作,但在一个极端情况下,它最终导致了问题。问题是我们的调试输出设置加载了一个专有 DLL 以在调试输出中包含版本信息。如果我们的 DLL 被快速加载和卸载并且在后台有足够多的事情导致这个版本信息读取速度很慢,那么它可能最终发生在进程在 PROCESS_DETACH 中等待的时间,从而导致死锁。

对于未来,我决定永远不要在 DllMin 中等待任何东西,因为我等待的任何东西都可能在某些极端情况下或在其他人向某个被触及的类添加功能之后,导致加载器锁死锁。

我希望这个建议对未来的人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-24
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    相关资源
    最近更新 更多