[Lazarus] Mutlithreaded Dll Callback crashes my Application

Sven Barth pascaldragon at googlemail.com
Thu Aug 26 22:06:26 CEST 2010


On 26.08.2010 20:52, Alexander Grau wrote:
>
> 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).

It's not only initializing the thread local storage (which is Windows 
only by the way, the threadvar system on e.g. Linux might have a 
different name), but also the exception and the I/O system

>
> 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;

You should not forget to write how a class of type "tc" looks like :)

> B) Make the runtime aware that your application uses multiple threads in
> the first line of your application (.dpr):
> IsMultithread:=true;
>

This is not needed. That is set to true automatically if a thread is 
created inside FPC.

> (This will make FPC routines to perform locks here and there.)
> C) Do not use external threads at all - use FPC threads.
>

Should be put at the top of the list ^^

> 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;
>

The number in InitThread is the initial stack length and as I was a bit 
lazy I simply set it to a huge number. So don't nail me on that one :D

You might also replace the "someFunc(param)" with "{ do something 
threaded }" or something like that.

>
> 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.

I don't know whether this works (reliably) when the threadvars haven't 
been allocated yet. I don't even know what happens if you access 
unallocated threadvars O.o

Regards,
Sven




More information about the Lazarus mailing list