Code Monkey home page Code Monkey logo

Comments (6)

tnie avatar tnie commented on September 14, 2024

动态库中子线程被突然掐断(强行结束)!
https://github.com/tnie/YDData2/issues/228
https://github.com/tnie/YDData2/issues/227

log4z 作者表示 暂时不会加动态库

除非明确主线程等待,否则都会被动态库强行结束?——非全局变量/静态变量的析构都在主线程之内,肯定会等;也只有全局变量、静态变量的析构会在主线程 main() 结束之后

可是如果不是动态库中的全局变量/静态变量,而是主程序中的就不存在被强行结束的困惑。

from testdll.

tnie avatar tnie commented on September 14, 2024

如果从未意识到上述状况的存在,那么理解下面这段话可能就有些困难:

Consider a DLL that creates worker threads as part of its initialization. Upon DLL cleanup, it is necessary to synchronize with all the worker threads to ensure that the data structures are in a consistent state and then terminate the worker threads.Today, there is no straightforward way to completely solve the problem of cleanly synchronizing and shutting down DLLs in a multithreaded environment. This section describes the current best practices for thread synchronizing during DLL shutdown. 引用来源

由以下描述看出,在 DllMain 中并无有效手段可以用来解决我们的问题。

By the time DllMain is called at process exit, all the process’s threads have been forcibly cleaned up and there is a chance that the address space is inconsistent. Synchronization is not required in this case. In other words, the ideal DLL_PROCESS_DETACH handler is empty. 引用来源

问题核心在于 DLL 什么时候卸载,为什么卸载 DLL 并未等其(指 DLL 中的)静态变量析构执行完毕。所以,问题变成了 crt 相关了。

from testdll.

tnie avatar tnie commented on September 14, 2024

如果动态库(启用线程)析构中不 join() 子线程,只是做些耗时操作:打印结果多样,以后者居多

hModule.0F630000 lpReserved.00EFF980
Process attach.
> 主线程开始
> 主线程结束
hModule.0F630000 lpReserved.00000000
Thread attach.
hModule.0F630000 lpReserved.00000001
Process detach.
子线程第0次析构倒计时;
子线程第1次析构倒计时;
子线程第2次析构倒计时;
子线程第3次析构倒计时;
...
子线程第18次析构倒计时;
子线程第19次析构倒计时;
请按任意键继续. . .

以下无 Process detach. 的情形可能源于创建线程后既没有 join() 也未 detach()

hModule.0F6D0000 lpReserved.0098F5B4
Process attach.
> 主线程开始
> 主线程结束
hModule.0F6D0000 lpReserved.00000000
Thread attach.
请按任意键继续. . .

In a Windows C++ DLL, all global objects (including static members of classes) will be constructed just before the calling of the DllMain with DLL_PROCESS_ATTACH, and they will be destroyed just after the call of the DllMain with DLL_PROCESS_DETACH. 摘自

答主用了 destroy 而非 destruct,两者等价还是另有玄机?

动态库中的全局变量、静态变量的析构在 DLL_PROCESS_DETACH 之后执行,而采用 Load-Time Dynamic Linking (区别于 Run-Time Dynamic Linking)方式的程序,DLL_PROCESS_DETACH 即意味着进程结束(执行 exist()?),所以分离的两者如果纠缠的?——会让析构执行到末尾,但也会杀掉所有线程?

If the process is terminating (the lpvReserved parameter is non-NULL), all threads in the process except the current thread either have exited already or have been explicitly terminated by a call to the ExitProcess function, which might leave some process resources such as heaps in an inconsistent state. 引用来源

from testdll.

tnie avatar tnie commented on September 14, 2024

网上有些帖子提到,动态库中全局变量/静态变量的析构函数未被执行,但我实际测试在 DLL 不启用线程时,在 main() 函数 return 之后,静态变量的析构依旧会执行!

from testdll.

tnie avatar tnie commented on September 14, 2024

能否捕捉线程是执行完毕退出还是被强行终止的?以便进一步确认主线程退出时杀掉了(做了无效托管的)子线程

join after main 是无效的?main() 之外可以有线程吗?

from testdll.

tnie avatar tnie commented on September 14, 2024

在 dll 静态变量/全局变量的析构函数中指明 join() 的线程,进程退出时会被强行结束——这个到底是不是 msvc 的 bug?https://stackoverflow.com/questions/42535990/worker-threads-are-forcibly-terminated-prior-to-the-destruction-of-static-object

使用除了 msvc2015 之外的编译器测试:

  • g++ (Debian 4.9.2-10) 4.9.2 执行结果满足预期,会完整执行 .so 中的线程函数
  • msvc2017 执行结果同 msvc2015

没有解决方案:https://stackoverflow.com/questions/43110740/thread-created-by-static-object-deleted-before-dtor

It seems like you wanted to control the thread shutdown cleanly, did you work out a solution for that? – Phil Brubaker Apr 4 '17 at 1:40
unfortunately, no. The issue is that the thread is created from DLL static object. This object is destructed after the process already cleaned up all its threads. I found two clean, but not comfort solutions, and one comfort but dirty solution – Boris Bolshem Apr 4 '17 at 8:27

  1. Clean - make a done() functions, the user of lib should call it before the process ends. Kill a thread in done() function.
  2. Clean - User may wrap your object in its own object, and user's object should call done() function in its desctructor
  3. Dirty - do not care- the process is finishing, just let it kill all the used resources (in my case it will work) – Boris Bolshem Apr 4 '17 at 8:30

from testdll.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.