[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