[fpc-devel] Question regarding thread finalization

Michael Van Canneyt michael at freepascal.org
Sat Nov 27 18:12:57 CET 2010

Pierre muller has a better solution.

He uses TLS callbacks. His solution is finished, but is in need of testing.
If you want, I can send you his patch, and then you can test it too.

As for the DoneThread: your solution number 3 is the one to take. 
It is by far the safest. We'll need to implement it anyway like that
to fix the case of the TLS done callback and the DLL_DETACH_THREAD.


On Sat, 27 Nov 2010, Sven Barth wrote:

> Hello together!
> As you might now, I'm working on a (according to Michael maybe temporary) 
> solution for the clean up of external threads (see 
> http://bugs.freepascal.org/view.php?id=17300 ).
> My current state is that the collector thread which is used inside a 
> "program" is working correctly and now I'm going to tackle the problem of 
> DLLs.
> I've looked at the necessary include files some time now and I might have 
> spotted a potential problem with thread finalization in DLLs.
> Consider the following: in a DLL we start a thread and once it has done its 
> duty we call "EndThread" and return from the thread method (I'm thinking in 
> terms of "BeginThread" not "TThread" for this example).
> After we've returned from the method Windows will call our DLL's entry point 
> (and that of any other loaded DLL) with DLL_THREAD_DETACH where we call 
> "DoneThread" because the current thread is not the "main" thread (another 
> interesting story...).
> The call of "DoneThread" is decorated with a comment "Assume everything is 
> idempotent there". I'm hereby proposing that this assumption is not correct.
> I've looked at "EndThread" and "DoneThread". "EndThread" calls the thread 
> manager's "EndThread" method which on Windows calls "DoneThread"(!) and the 
> API method "ExitThread".
> "DoneThread" finalizes the RTL for that thread and starts with the WideString 
> manager (not looked into that) and continues with the heap. Now the first 
> thing the heap does is getting the address of its "freelists" record (which 
> is a threadvar!) and plays around a bit with its contents (not really 
> important for this discussion). "DoneThread" then continues finalizing other 
> parts of the RTL and finally calls the thread managers "ReleaseThreadVars" 
> method.
> I sincerely hope that every alarm bell rings now. By calling "DoneThread" 
> twice in a DLL we are basically accessing already freed memory: the thread 
> var data.
> As this is a very serious problem I now ask you how this should be solved:
> 1) keep it as it is (I hope not O.o)
> 2) fullfill the assumption and check the code which is called by "DoneThread" 
> to be idempotent (which can break again at any time)
> 3) stop assuming that "DoneThread" is idempotent and do some checks here. 
> E.g. by checking whether TlsGetValue(TLSKey) is Nil before calling 
> "DoneThread" in DLL_THREAD_DETACH, which means that a) the RTL was never 
> initialised (a thread that was created before DLL_PROCESS_ATTACH and never 
> called into the DLL's code - see below) or b) the thread was already 
> finalized.
> Problem 3a is the following:
> A thread is created in an application. Now the main thread loads a FPC 
> library and some time after that the thread exits (it has never called any 
> method in the DLL). Now the DLL receives a DLL_THREAD_DETACH and currently 
> blindly finalizes a never initialized RTL (because it has never received a 
> DLL_THREAD_ATTACH call for this thread!).
> Modifying the RTL in this way might also solve the external thread problem 
> for DLLs (I still have to think that one through, though).
> Regards,
> Sven
> _______________________________________________
> fpc-devel maillist  -  fpc-devel at lists.freepascal.org
> http://lists.freepascal.org/mailman/listinfo/fpc-devel

More information about the fpc-devel mailing list