Results 1 to 10 of 48

Thread: Cheb's project will be here.

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #9
    Trying trunk 3.3.1 aka the larva of 3.2.

    I was glad to see the exception handling in threads created by a DLL is working now out of the box. Interestingly, it seems having no conflicts with existing Win32 SEH handlers (as each driver DLL you load likely installs its own, I tested and confirmed that) but RTL 3.3.1 doesn't install its own handler.

    I wasn't able to figure it out *how* exception handling of 3.3.1 works, it's a black box for me now.

    Test:
    Code:
    program thrtesta;
    {$mode objfpc}
    {$apptype console}
    {$longstrings on}
    uses
    {$ifdef unix}
      cthreads,
    {$endif}
      SysUtils,
      Classes
      {$ifdef unix}
        , dl
      {$else}
        , windows
      {$endif}
      ;
    type
      TTestThread = class(TThread)
      protected
        procedure Execute; override;
      end;
    
      procedure TTestThread.Execute;
      begin
        WriteLn('> A');
        try
          byte(nil^):= 0;
        except
          WriteLn('exe thread ID=',GetCurrentThreadId()
            ,' catch: ',(ExceptObject as Exception).Message);
        end;
        WriteLn('< A');
      end;
     
      function PCharToString(P: PAnsiChar): Utf8String;
      var
        i: integer;
        p2: PAnsiChar;
      begin
        if not Assigned(p) then Result:= ''
        else begin
          p2:= p;
          i:= 0;
          While p2^ <> #0 do begin
            inc(p2);
            inc(i);
          end;
          SetLength(Result, i);
          MOVE(p^, Result[1], i);
        end;
      end; 
    
    var
      t: TTestThread;
      dllhandle: {$ifdef unix} pointer {$else} THandle {$endif};
      mypath: string;
      {$ifdef unix}
        ufn, upn: Utf8String;
      {$else}
        wfn: UnicodeString;
        wpn: AnsiString;
      {$endif}
      thrproc: procedure; cdecl = nil;
     
    begin
      WriteLn('the exe is built using fpc '
        ,{$I %FPCVERSION%},'/',{$I %FPCTARGETOS%},'/',{$I %FPCTARGETCPU%});
      WriteLn('main thread ID=', GetCurrentTHreadId());         
      t := TTestThread.Create(False);
      WriteLn('exe thread created'); 
      try
        t.WaitFor;
      finally
        t.Free;
      end;
      WriteLn('exe thread terminated');
      WriteLn('loading the DLL...');
      mypath:= ExtractFilePath(ParamStr(0))
        + {$ifdef unix} 'libthrtestb.so' {$else} 'thrtestb.dll' {$endif};
      WriteLn('path is ', mypath);
      {$ifdef unix}
        ufn:= mypath; 
        dllhandle:= dlopen(PAnsiChar(nu8), RTLD_NOW);
        if not Assigned(DLL) then begin
          WriteLn('failed to load: ',PCharToString(dlerror()));
          Halt(0);
        end;
        upn:= 'thrproc';
        pointer(thrproc):= dlsym(dllhandle, PAnsiChar(upn));
      {$else}
        wfn:= mypath;
        SetLastError(0);
        dllhandle:= LoadLibraryW(PUcs2Char(wfn));
        if dllhandle = 0 then begin
          WriteLn('failed to load.');
          Halt(0);
        end;
        wpn:= 'thrproc';
        pointer(thrproc):= windows.GetProcAddress(dllhandle, PAnsiChar(wpn));
      {$endif}
      if not Assigned(pointer(thrproc)) then begin
        WriteLn('failed to load the procedure.');
        Halt(0);
      end;
    
      WriteLn('invoking the dll...');
      try
        thrproc;
      except
        WriteLn('exe thread ID=',GetCurrentThreadId()
          ,' catch: ',(ExceptObject as Exception).Message);
      end;
      WriteLn('unloading the dll...');
      {$ifdef unix}
        dlClose(dllhandle);
      {$else}
        FreeLibrary(dllhandle);
      {$endif}
      WriteLn('done.');
    end.
    Code:
    library thrtestb;
    {$mode objfpc}
    {$apptype console}
    {$longstrings on}
    uses
    {$ifdef unix}
      cthreads,
    {$endif}
      SysUtils,
      Classes;
    type
      TTestThread = class(TThread)
      protected
        procedure Execute; override;
      end;
    
      procedure TTestThread.Execute;
      begin
        WriteLn('> X');
        try
          WriteLn('> Y');
          try
            WriteLn('> Z');
            try
              byte(nil^):= 0;
            except
              WriteLn('dll thread ID=',GetCurrentThreadId()
                ,' catch in block Z: ',(ExceptObject as Exception).Message);
            end;
            WriteLn('< Z');
          except
            WriteLn('dll thread ID=',GetCurrentThreadId()
              ,' catch in block Y: ',(ExceptObject as Exception).Message);
          end;
          WriteLn('< Y');
        except
          WriteLn('dll thread ID=',GetCurrentThreadId()
            ,' catch in block X: ',(ExceptObject as Exception).Message);
        end;
        WriteLn('< X');
      end;
    
      procedure MyMainProc; cdecl;
      var t: TThread;
      begin
        WriteLn('the dll is built using fpc '
          ,{$I %FPCVERSION%},'/',{$I %FPCTARGETOS%},'/',{$I %FPCTARGETCPU%});
        try
          t := TTestThread.Create(False);
          WriteLn('dll thread created'); 
          try
            t.WaitFor;
          finally
            t.Free;
          end;
        except
          WriteLn('dll thread ID=',GetCurrentThreadId()
            ,' catch in main proc: ',(ExceptObject as Exception).Message);
        end;
        WriteLn('the dll is done.')
      end;
     
    exports
      MyMainProc name 'thrproc';
    begin
    // do nothing.
    // The initialization sections DO NOT WORK in Linux for DLLs. And never will.
    end.
    Still a crash-to-desktop in 3.0.4:
    the exe is built using fpc 3.0.4/Win32/i386
    main thread ID=6444
    exe thread created
    > A
    exe thread ID=6736 catch: Access violation
    < A
    exe thread terminated
    loading the DLL...
    path is d:chentrahmodulesteststhrtestb.dll
    invoking the dll...
    the dll is built using fpc 3.0.4/Win32/i386
    dll thread created
    > X
    > Y
    > Z
    An unhandled exception occurred at $1000165F:
    EAccessViolation: Access violation
    Works perfectly in 3.3.1, the 17-year old bug finally closed:
    the exe is built using fpc 2.6.4/Win32/i386
    main thread ID=780
    exe thread created
    > A
    exe thread ID=6232 catch: Access violation
    < A
    exe thread terminated
    loading the DLL...
    path is d:chentrahmodulesteststhrtestb.dll
    invoking the dll...
    the dll is built using fpc 3.3.1/Win32/i386
    dll thread created
    > X
    > Y
    > Z
    dll thread ID=6076 catch in block Z: Access violation
    < Z
    < Y
    < X
    the dll is done.
    unloading the dll...
    done.
    On the engine front, I postpone trying 3.3.1 to autumn 2020 (sadly also postponing x86-64 support that requires it) and concentrate on making my engine usable using 3.0.4.
    The reason is difference in RTTI that necessitates making adjustments to my persistency system (and debugging them, dammit!)


    It will be ready in a month or two, with a simple asteroids game so that I could finally shave after all those years.
    Last edited by Chebmaster; 22-03-2020 at 09:24 AM.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •