[fpc-pascal] Exception handling and .dylibs on MacOS

Adriaan van Os adriaan at adriaan.biz
Thu Apr 3 14:47:32 CEST 2025


I recall this thread from last October

> I reported this, with a test program, as bug #40950 
> <https://gitlab.com/freepascal.org/fpc/source/-/issues/40950>.

The problem is that the fpc RTL, with its global variables, is duplicated in the .dylib as well as 
in the main program, which confuses the exception handling code. To resolve that, I have been 
experimenting with replacing exception-handling global variables in the RTL with functions and 
implementing those functions once (not twice) in a separate dynamic library. For example, adding 
rtl/inc/except.inc

{$ifdef FPC_HAS_EXTERNAL_EXCEPTION_GLOBALS}
function GetExceptAddrStack: PPExceptAddr; cdecl; external;
function GetExceptObjectStack: PPExceptObject; cdecl; external;
function GetExceptTryLevel: PObjpasInt; cdecl; external;

{$else}
{$ifdef FPC_HAS_FEATURE_THREADING}
ThreadVar
{$else FPC_HAS_FEATURE_THREADING}
Var
{$endif FPC_HAS_FEATURE_THREADING}
   ExceptAddrStack   : PExceptAddr;
   ExceptObjectStack : PExceptObject;
   ExceptTryLevel    : ObjpasInt;
{$endif}


etcetera. And then

unit exceptvars;

interface

   uses
     cthreads;

   type
     ObjpasInt = Longint;
     PObjpasInt = ^ObjpasInt;

function GetExceptAddrStack: PPExceptAddr; cdecl; public;
function GetExceptObjectStack: PPExceptObject; cdecl; public;
function GetExceptTryLevel: PObjpasInt; cdecl; public;

implementation

threadvar
   ExceptAddrStack   : PExceptAddr;
   ExceptObjectStack : PExceptObject;
   ExceptTryLevel    : ObjpasInt;

function GetExceptAddrStack: PPExceptAddr; cdecl; public;
begin
   GetExceptAddrStack := @ExceptAddrStack
end;

function GetExceptObjectStack: PPExceptObject; cdecl; public;
begin
   GetExceptObjectStack  := @ExceptObjectStack
end;

function GetExceptTryLevel: PObjpasInt; cdecl; public;
begin
   GetExceptTryLevel := @ExceptTryLevel
end;

begin
end.


and

library lib;

   uses
     exceptvars;

exports
   GetExceptAddrStack,
   GetExceptObjectStack,
   GetExceptTryLevel;

begin
end.


Now, the example code in the bug report 
<https://gitlab.com/freepascal.org/fpc/source/-/issues/40950> (when linked to the .dylib with the 
exception variables) no longer crashes and the exception is handled gracefully. Wel, actually I 
have to add an

erroraddr := nil

manually before exiting, because that variable and others need also be included in the 
exception-globals dylib (in the same way). I think these are the following, but correct me if I 
forget one:

erroraddr
errrorcode
errorbase
ErrorProc

Well, in what form will a patch along these lines be accepted ? I really need this to be fixed.

Another idea, that should work but that I didn't test yet, is to store the mentioned variables with 
pthread_getspecific and pthread_setspecific. In that case also, there is no duplication of them. An 
exception-globals dylib would not be needed, but it might be slower ?

Regards,

Adriaan van Os



More information about the fpc-pascal mailing list