I recall this thread from last October
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