[Lazarus] Mutlithreaded Dll Callback crashes my Application

Maik Wojcieszak maikwo at googlemail.com
Wed Aug 25 13:53:42 CEST 2010


Alexander,

I found something in the lazarus package for vortex :

{ FPC specific thread create function to replace Vortex's thread create.
 This is required because FPC doesn't work when C libraries create their own
 threads}

This may lead us to a solution I guess.
Some more background about that would be nice. Is this documented anywhere ?

Maik

Alexander Grau schrieb:
> Hello Maik!
>
> I have tried out your test program, and I get the crash too.  However 
> your program is already doing 10 things at the same time ;-) - This is 
> too difficult to find out the real problem - you need to scale down 
> everything ... So, I have written a minimal test program for you here 
> to start with - it works for me (no crash), how does it work at your 
> side?
>
> Regards,
> Alexander
>
>
> program project1;
>
> {$mode objfpc}{$H+}
>
> uses
>  {$IFDEF UNIX}{$IFDEF UseCThreads}
>  cthreads,
>  {$ENDIF}{$ENDIF}
>  Classes,
>  sysutils
>  { you can add units after this };
>
> {$R project1.res}
>
> type
>  MT_THREAD_HANDLE   = Pointer;
>
>  tdummy = class
>    name: string;
>    constructor create(aname: string);
>    procedure test;
>  end;
>
>
> function vcmtdll_NewThread: MT_THREAD_HANDLE; stdcall; external 
> 'vcmtdll.dll';
> procedure vcmtdll_DeleteThread(ahandle : MT_THREAD_HANDLE); stdcall; 
> external 'vcmtdll.dll';
> procedure vcmtdll_RegisterCallback(ahandle : MT_THREAD_HANDLE; pCBFunc 
> : Pointer; pCBData : Pointer); stdcall; external 'vcmtdll.dll';
> procedure vcmtdll_StartThread(ahandle : MT_THREAD_HANDLE; iDelay : 
> Cardinal); stdcall; external 'vcmtdll.dll';
>
> var
>  handle: MT_THREAD_HANDLE;
>
>
> constructor tdummy.create(aname: string);
> begin
>  inherited create;
>  name:=aname;
> end;
>
> procedure tdummy.test;
> begin
>  writeln('tdummy.test: ', name);
> end;
>
> procedure OnExecuteClb(pCBData : Pointer); cdecl;
> var
>  dummy: tdummy;
>  i: integer;
> begin
>  writeln('onExecuteClb');
>  dummy:=tdummy.create('callbackdummy');
>  tdummy(pCBData).test;
>  for i:=1 to 30 do
>    dummy.test();
>  dummy.free;
> end;
>
> var
>  globaldummy: tdummy;
>
> begin
>  globaldummy:=tdummy.create('globaldummy');
>
>  writeln('start');
>  Handle  := vcmtdll_NewThread();
>  writeln('handle=', hexStr(handle));
>
>  vcmtdll_RegisterCallback(Handle, @OnExecuteClb, globaldummy);
>  vcmtdll_StartThread(handle, 0);
>
>  sleep(1000);
>
>  vcmtdll_DeleteThread(handle);
>  writeln('bye');
>  globaldummy.free;
> end.
>
>
>
>
>
>
>
> Maik Wojcieszak schrieb:
>> Hi,
>>
>> After my holiday I've done done more research on this problem and hope I
>> can get an answer while continuing this thread.
>>
>> My Versions (again)
>>
>> Lazarus IDE v0.9.28.2 Beta
>> MS Windows XP Prof DE sp3
>> FPC Version 2.2.4
>>
>> What I basically do is passing a pointer to a calback funtion to a dll
>> writte in c++ (Visual Studio 2005) and call it from there.
>> ** The follwing code is from the example attached to this mail **
>>
>> procedure OnExecuteClb(pCBData : Pointer); cdecl;
>> begin
>> ...
>> end;
>>
>> The function is passed to the dll like this
>>
>> ...
>>     FHandle    := uVCMTDLL.vcmtdll_NewThread();
>>     uVCMTDLL.vcmtdll_RegisterCallback(FHandle, at OnExecuteClb,self);
>> ...
>>
>>
>> The test includes a dll which has the following interface
>>
>> ...
>> #define VCMTDLL_API __declspec(dllexport)
>>
>> namespace VCMTDLL {
>>
>> typedef void* MT_THREAD_HANDLE;
>>
>> extern "C" {
>>
>> VCMTDLL_API MT_THREAD_HANDLE vcmtdll_NewThread();  // create a new
>> thread object
>> VCMTDLL_API void vcmtdll_DeleteThread(MT_THREAD_HANDLE ahandle); //
>> delete an existing thread object
>> VCMTDLL_API void vcmtdll_RegisterCallback(MT_THREAD_HANDLE ahandle,
>> void* pCBFunc, void* pCBData); // pass a callback to execute inside the
>> thread context
>> VCMTDLL_API void vcmtdll_StartThread(MT_THREAD_HANDLE ahandle, unsigned
>> int iDelay); // start the execution with a delay of <iDelay> 
>> milliseconds
>>
>> }// extern "C"
>>
>> ...
>>
>> with a loop in the callback function everything is fine
>>
>> ...
>>    x := 0;
>>    while x < 100 do
>>    begin
>>      x := x + 1;
>>    end;
>> ...
>>
>> I can execute it without problems.
>>
>> BUT if I create and destroy an object inside the procedure the app
>> crahes or hangs after several runs of the test (between 1 an 10 starts).
>>
>> the object:
>>
>> ...
>> TVCMTDummyObject = class
>> private
>> public
>>       Tag : Integer;
>> end;
>> ...
>>
>> the code in the callback
>>
>> ...
>>    a := TVCMTDummyObject.Create;
>>    a.Free;
>> ...
>>
>> Another problem is that a PostMessage from the callback's thread context
>> immediatly crashes the app. But this may be resolved later.
>>
>> If there is anybody who uses a similar mechanism in his lazarus project
>> and knows how to solve this problem it'd be great.
>> The demo project together with dll is attached too.
>>
>> Best Regards
>> Maik
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> -- 
>> _______________________________________________
>> Lazarus mailing list
>> Lazarus at lists.lazarus.freepascal.org
>> http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
>>   
>
>
> -- 
> _______________________________________________
> Lazarus mailing list
> Lazarus at lists.lazarus.freepascal.org
> http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus
>





More information about the Lazarus mailing list