Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2024-10

AllocateThreadVars ?

10 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Adriaan van Os

I have a program on MacOS that calls CoreAudio which calls the application back in a so-called AURendererCallback in a separate (com.apple.audio.IOThread.client) thread. This is a pthread created by the system software, not by the FreePascal RTL.

In that thread, a FreePascal try except block doesn't catch an exception. A globally installed TExceptProc does. if I look in the RTL code, it looks like a thread created with BeginThread does some extra things, like calling SysAllocateThreadVars. A comment notes that exception handling depends on it.

So, it seems plausible that SysAllocateThreadVars (or the AllocateThreadVars method of the current TThreadManager) must be called once for pthreads created by the system software ? How ? Obviously I couldn't use a threadvar that tells me whether AllocateThreadVars has been called already ?

Regards,

Adriaan van Os

Adriaan van Os
to Adriaan van Os
Adriaan van Os wrote 5 lines
In that thread, a FreePascal try except block doesn't catch an exception. A globally installed TExceptProc does. if I look in the RTL code, it looks like a thread created with BeginThread does some extra things, like calling SysAllocateThreadVars. A comment notes that exception handling depends on it.

This could have been my fault. So, for the moment, please forget this message.

Regards,

Adraiaan van Os

Sven Barth
to Adriaan van Os: I have a program on MacOS that calls CoreAudio which calls the application back in a…

Adriaan van Os via fpc-pascal schrieb am
Mi., 9. Okt. 2024, 16:44:

Show quoted text 21 lines
I have a program on MacOS that calls CoreAudio which calls the application back in a so-called AURendererCallback in a separate (com.apple.audio.IOThread.client) thread. This is a pthread created by the system software, not by the FreePascal RTL. In that thread, a FreePascal try except block doesn't catch an exception. A globally installed TExceptProc does. if I look in the RTL code, it looks like a thread created with BeginThread does some extra things, like calling SysAllocateThreadVars. A comment notes that exception handling depends on it. So, it seems plausible that SysAllocateThreadVars (or the AllocateThreadVars method of the current TThreadManager) must be called once for pthreads created by the system software ? How ? Obviously I couldn't use a threadvar that tells me whether AllocateThreadVars has been called already ?

You already wrote that you might have found a different cause, but nevertheless to clarify: the RTL initialization for the thread (which includes AllocateThreadVars) should already be done transparently by the RTL through hooks provided by pthread.

Regards,
Sven

Adriaan van Os
to Sven Barth
Sven Barth wrote 30 lines
Adriaan van Os via fpc-pascal < > schrieb am Mi., 9. Okt. 2024, 16:44: I have a program on MacOS that calls CoreAudio which calls the application back in a so-called AURendererCallback in a separate (com.apple.audio.IOThread.client) thread. This is a pthread created by the system software, not by the FreePascal RTL. In that thread, a FreePascal try except block doesn't catch an exception. A globally installed TExceptProc does. if I look in the RTL code, it looks like a thread created with BeginThread does some extra things, like calling SysAllocateThreadVars. A comment notes that exception handling depends on it. So, it seems plausible that SysAllocateThreadVars (or the AllocateThreadVars method of the current TThreadManager) must be called once for pthreads created by the system software ? How ? Obviously I couldn't use a threadvar that tells me whether AllocateThreadVars has been called already ? You already wrote that you might have found a different cause, but nevertheless to clarify: the RTL initialization for the thread (which includes AllocateThreadVars) should already be done transparently by the RTL through hooks provided by pthread.

Yes, I found the hook in cthreads.pp. Thanks for the reply.

In a small test program, exception handling works, in the main thread, with BeginThread as well as with pthread_create. In the big program, it doesn't. So the mystery still to solve, is why ....

Regards,

Adriaan van Os

Adriaan van Os
to Sven Barth: Adriaan van Os via fpc-pascal schrieb am Mi., 9. Okt. 2024, 16:44: You already wrote…
Show quoted text 11 lines
Sven Barth via fpc-pascal wrote: > You already wrote that you might have found a different cause, but > nevertheless to clarify: the RTL initialization for the thread (which > includes AllocateThreadVars) should already be done transparently by the > RTL through hooks provided by pthread. Yes, I found the hook in cthreads.pp. Thanks for the reply. In a small test program, exception handling works, in the main thread, with BeginThread as well as with pthread_create. In the big program, it doesn't. So the mystery still to solve, is why ....

Matbe this is related to <https://gitlab.com/freepascal.org/fpc/source/-/issues/12974> as the code resides in a dynamic library (written in Pascal and called into from a main program, also written in Pascal)

Regards,

Adriaan van Os

Adriaan van Os
to Sven Barth: Adriaan van Os via fpc-pascal schrieb am Mi., 9. Okt. 2024, 16:44: You already wrote…
Show quoted text 6 lines
> In a small test program, exception handling works, in the main thread, with BeginThread as well as > with pthread_create. In the big program, it doesn't. So the mystery still to solve, is why .... Maybe this is related to <https://gitlab.com/freepascal.org/fpc/source/-/issues/12974> as the code resides in a dynamic library (written in Pascal and called into from a main program, also written in Pascal)

Just as decribed in <https://gitlab.com/freepascal.org/fpc/source/-/issues/12974> the exception is handled by FPC in this case

   try
    SysUtils.RaiseLastOSError;
   except;
     writeln( 'handled adriaan`s crash exception')
   end;

but not in this case

   try
     theInt := pinteger(1234)^ }
   except;
     writeln( 'handled adriaan`s crash exception')
   end;

So, this does seem related, although on another platform.

Regards,

Adriaan van Os

Adriaan van Os
to Sven Barth: Adriaan van Os via fpc-pascal schrieb am Mi., 9. Okt. 2024, 16:44: You already wrote…
Show quoted text 6 lines
> In a small test program, exception handling works, in the main thread, with BeginThread as well as > with pthread_create. In the big program, it doesn't. So the mystery still to solve, is why .... Maybe this is related to <https://gitlab.com/freepascal.org/fpc/source/-/issues/12974> as the code resides in a dynamic library (written in Pascal and called into from a main program, also written in Pascal)

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

Regards,

Adriaan van Os

Adriaan van Os
to Sven Barth: Adriaan van Os via fpc-pascal schrieb am Mi., 9. Okt. 2024, 16:44: You already wrote…

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

Adriaan van Os
Sven Barth wrote 8 lines
Adriaan van Os < > schrieb am Do., 3. Apr. 2025, 14:47: Well, in what form will a patch along these lines be accepted ? I really need this to be fixed. In no form, cause this is not a way in which we want to see this fixed.

So, how are you going to fix this ? It is easy to say that and leave the bug open for ever.

Regards,

Adriaan van Os

Sven Barth
to Adriaan van Os

Adriaan van Os schrieb am Fr., 4. Apr. 2025, 15:30:

Show quoted text 13 lines
Sven Barth wrote: > Adriaan van Os < > > schrieb am Do., 3. Apr. 2025, 14:47: > > Well, in what form will a patch along these lines be accepted ? I > really need this to be fixed. > > > In no form, cause this is not a way in which we want to see this fixed. So, how are you going to fix this ? It is easy to say that and leave the bug open for ever.

Better that than "fixing" something in a way that *will* break something else. And your suggestion *will* do that, because it mixes object instances from different instances of the RTL which will lead for example to "as" and "is" breaking, not to mention if someone would do that with two different, incompatible versions of the RTL. It working for your specific case does not mean that it will work in general and as such this has no place in the RTL.

Regards,
Sven