[Lazarus] Mutlithreaded Dll Callback crashes my Application

Alexander Grau alex at grauonline.de
Thu Aug 26 20:52:20 CEST 2010


Sven Barth schrieb:
> Am 25.08.2010 23:07, schrieb José Mejuto:
>>>> On the other hand, if Unix needs one thread creation then it should be
>>>> automagically done in the initialization section of cthreads, do not ?
>> SB>  This might indeed be a solution.
>>
>> If windows have the same problem, threading system should be
>> initialized in... somewhere automagically as windows multithread is
>> always present.
>>
>
> This only solves one point (but is needed nevertheless).
>
> As I've showed in the last message to Alexander yesterday evening you 
> need to initialize some things PER THREAD and I don't know whether 
> this can be automised. We might need to ask the FPC devs for help 
> regarding this. Perhaps the first time a threadvar in this new thread 
> is accessed might be a good possibilty, but I don't know (yet) how we 
> could track whether this is the first call, because threadvars are not 
> yet allocated (hen-egg-problem). I'll have to take a deeper look into 
> the threading system on Win32 :)
>
> Regards,
> Sven

I'm currently trying to summarize all aspects we discussed to add them 
to the FreePascal Multithreading wiki page (see below)  -  did I forget 
something that should be mentioned?

Thanks,
Alexander



External threads


To make Free Pascal's threading system to work properly, each newly 
created FPC thread needs to be initialized (more exactly, the thread 
local storage per thread needs to be initialized so threadvars and heap 
are working). That is fully automatically done for you if you use 
BeginThread (or indirectly by using the TThread class). However, if you 
use threads that were created without BeginThread (i.e. external 
threads),  additional work (currently) might be required. External 
threads also include those that were created in external C libraries 
(.DLL/.so). 


Things to consider when using external threads (might not be needed in 
all or future compiler versions):


A) Initialize the FPC's threading system by creating a dummy thread:

  { initialise threading system }
   with tc.create(false) do
   begin
     waitfor;
     free;
   end;  
  
B) Make the runtime aware that your application uses multiple threads in 
the first line of your application (.dpr): 

IsMultithread:=true;

(This will make FPC routines to perform locks here and there.)  

C) Do not use external threads at all - use FPC threads.

D) If for some reason this doesn't work for you, try this code in your 
external thread function:
 
function ExternalThread(param: Pointer): LongInt; stdcall;
var
  tm: TThreadManager;
begin
  GetThreadManager(tm);
  tm.AllocateThreadVars;
  InitThread(100000000);
  someFunc(param);
  Result:=0;
end;  



How to identify if your code is executed in an external thread context

1. Ask the OS for the ID of the current thread at your application's start

Win32: WriteLn('Thread ID=', GetCurrentThreadID);
Darwin: WriteLn('Thread ID=', GetThreadID); 
Linux: Writeln('Thread ID=', TThreadID(pthread_self) );

2. Ask again for the ID of the current thread inside the thread function 
and compare this by the result of step 1.





More information about the Lazarus mailing list