Sign in Join

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

Mailing lists / lazarus / 2025-09

SIGSEV in TScreen.FindNonDesignerDataModule

21 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

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

Luca Olivetti

As per the subject, occasionally (but not always) I get a SIGSEV in TScreen.FindNonDesignerDataModule (in includes/screen.in)

function TScreen.FindNonDesignerDataModule(const DataModuleName: string
   ): TDataModule;
var
   i: Integer;
begin
   for i:=0 to FDataModuleList.Count-1 do
   begin
     Result:=TDataModule(FDataModuleList[i]);
     if (not (csDesigning in Result.ComponentState)) <<<<<<<<<<< here
     and (CompareText(Result.Name, DataModuleName) = 0) then
       Exit;
   end;
   Result := nil;
end;

It happens when I create a form that's not in the auto create forms. For the time being, I set Application.FindGlobalComponentEnabled to false before creating the form

    Application.FindGlobalComponentEnabled:=false;
    LocForm:=TFormWtss.Create(nil);
    Application.FindGlobalComponentEnabled:=true;
    ;
    try
       LocForm.ShowModal;
    finally
      LocForm.Free;
    end;

but what could be causing it?

I have several datamodules used by threads, so I thought that maybe the function is non thread safe, but the creation of said datamodules is done in the main thread.

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Juha Manninen
to Luca Olivetti

On Mon, Sep 15, 2025 at 3:37?PM Luca Olivetti via lazarus <

Show quoted text 20 lines
wrote: As per the subject, occasionally (but not always) I get a SIGSEV in TScreen.FindNonDesignerDataModule (in includes/screen.in) function TScreen.FindNonDesignerDataModule(const DataModuleName: string ): TDataModule; var i: Integer; begin for i:=0 to FDataModuleList.Count-1 do begin Result:=TDataModule(FDataModuleList[i]); if (not (csDesigning in Result.ComponentState)) <<<<<<<<<<< here and (CompareText(Result.Name, DataModuleName) = 0) then Exit; end; Result := nil; end;

I don't know the code but there is a hard typecast which is always suspicious.
Please test with the provided patch. It throws an exception with a proper message if the type is wrong.

It happens when I create a form that's not in the auto create forms.

For the time being, I set Application.FindGlobalComponentEnabled to false before creating the form

I am curious. What is FindGlobalComponentEnabled for?

Juha
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20250915/816921e3/attachment.htm> -------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Debug-FDataModuleList.patch
Type: text/x-patch
Size: 1166 bytes
Desc: not available
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20250915/816921e3/attachment.bin>

Reply by email

Luca Olivetti
to Juha Manninen

El 15/9/25 a les 20:00, Juha Manninen via lazarus ha escrit:

Show quoted text 26 lines
On Mon, Sep 15, 2025 at 3:37?PM Luca Olivetti via lazarus < <mailto:>> wrote: As per the subject, occasionally (but not always) I get a SIGSEV in TScreen.FindNonDesignerDataModule (in includes/screen.in <http:// screen.in>) function TScreen.FindNonDesignerDataModule(const DataModuleName: string ? ?): TDataModule; var ? ?i: Integer; begin ? ?for i:=0 to FDataModuleList.Count-1 do ? ?begin ? ? ?Result:=TDataModule(FDataModuleList[i]); ? ? ?if (not (csDesigning in Result.ComponentState)) <<<<<<<<<<< here ? ? ?and (CompareText(Result.Name, DataModuleName) = 0) then ? ? ? ?Exit; ? ?end; ? ?Result := nil; end; I don't know the code but there is a hard typecast which is always suspicious.

I don't think it's a problem, it's defined as a TFPList and it's only managed with methods DoAddDataModule and DoRemoveDataModule, which have a TDataModule parameter.

Please test with the provided patch. It throws an exception with a proper message if the type is wrong.

Again, I don't think that's the case. Besides, there are a couple more functions that use FDataModuleList

Show quoted text 8 lines
It happens when I create a form that's not in the auto create forms. For the time being, I set Application.FindGlobalComponentEnabled to false before creating the form I am curious. What is FindGlobalComponentEnabled for?

No idea, but looking at the backtrace I found that it avoids calling that code :-D

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Juha Manninen
to Luca Olivetti

On Mon, Sep 15, 2025 at 9:09?PM Luca Olivetti via lazarus <

Show quoted text 6 lines
wrote: I don't think it's a problem, it's defined as a TFPList and it's only managed with methods DoAddDataModule and DoRemoveDataModule, which have a TDataModule parameter.

True. Besides, my patch does not help if the list contains garbage, meaning a TDataModule which was already freed. That is the most likely scenario. Why would you get a SIGSEGV otherwise? Such bugs are difficult to find. :(

Juha
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20250915/a029560d/attachment-0001.htm>

Reply by email

Martin Frb
to Luca Olivetti: As per the subject, occasionally (but not always) I get a SIGSEV in…
Luca Olivetti wrote 6 lines
but what could be causing it? I have several datamodules used by threads, so I thought that maybe the function is non thread safe, but the creation of said datamodules is done in the main thread.

No, idea. But if it happens reasonable often, and if you can do it on Linux => then run it in
? valgrind --tool=memcheck

And see if it reports any access to freed memory.
Valgrind has a good chance to catch it, even if it does not end in a crash (but instead the error is silently doing nothing). If it catches it, it will tell you were the mem was freed.

However memcheck may return empty handed if it is a thread issue (timing / race condition).

I will be away from Wednesday onwards. So there wont be replies from me then.

Reply by email

Luca Olivetti
to Juha Manninen: On Mon, Sep 15, 2025 at 9:09?PM Luca Olivetti via lazarus < True. Besides, my patch does…

El 15/9/25 a les 20:17, Juha Manninen via lazarus ha escrit:

Show quoted text 14 lines
On Mon, Sep 15, 2025 at 9:09?PM Luca Olivetti via lazarus < <mailto:>> wrote: I don't think it's a problem, it's defined as a TFPList and it's only managed with methods DoAddDataModule and DoRemoveDataModule, which have a TDataModule parameter. True. Besides, my patch does not help if the list contains garbage, meaning a TDataModule which was already freed. That is the most likely scenario. Why would you get a SIGSEGV otherwise? Such bugs are difficult to find. :(

As I said, my suspicion was that a thread was calling DoAddDataModule and/or DoRemoveDataModule, but I double checked and they're called by the main thread. I'll triple check again.
It's also possible that I'm corrupting that data structure with some stray pointer, but I couldn't reproduce it under the debugger, only on the production machine.
Oh, well, I'll keep hunting for the cause.

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Luca Olivetti
to Luca Olivetti

El 15/9/25 a les 20:35, Luca Olivetti via lazarus ha escrit:

Show quoted text 25 lines
El 15/9/25 a les 20:17, Juha Manninen via lazarus ha escrit: > On Mon, Sep 15, 2025 at 9:09?PM Luca Olivetti via lazarus > < <mailto:>> > wrote: > > > ??? I don't think it's a problem, it's defined as a TFPList and it's only > ??? managed with methods DoAddDataModule and DoRemoveDataModule, which > have > ??? a TDataModule parameter. > > > True. Besides, my patch does not help if the list contains garbage, > meaning a TDataModule which was already freed. That is the most likely > scenario. Why would you get a SIGSEGV otherwise? Such bugs are > difficult to find. :( As I said, my suspicion was that a thread was calling DoAddDataModule and/or DoRemoveDataModule, but I double checked and they're called by the main thread. I'll triple check again. It's also possible that I'm corrupting that data structure with some stray pointer, but I couldn't reproduce it under the debugger, only on the production machine. Oh, well, I'll keep hunting for the cause.

I found the problem, though I don't know how to solve it: I'm using fpweb (actually my own subclass of TFPHTTPServerHandler) in threaded mode. When a request for a file comes in, it instantiates a TSimpleFileModule(*), which is derived from TDataModule and in turns it calls DoAddDataModule. The problem, as I suspected, is that a TFPList is not thread safe.

Any hint?

Should I implement my own variant of TSimpleFileModule that creates the instance in a synchronized method?

(*) That's because I configure it in my server constructor
  TSimpleFileModule.BaseDir:=htmldir;
  TSimpleFileModule.IndexPageName:='index.html';
  TSimpleFileModule.RegisterDefaultRoute;
  ;
Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Luca Olivetti
to Luca Olivetti

El 15/9/25 a les 20:59, Luca Olivetti via lazarus ha escrit:

Show quoted text 37 lines
El 15/9/25 a les 20:35, Luca Olivetti via lazarus ha escrit: > El 15/9/25 a les 20:17, Juha Manninen via lazarus ha escrit: >> On Mon, Sep 15, 2025 at 9:09?PM Luca Olivetti via lazarus >> < <mailto: >> ide.org>> wrote: >> >> >> ??? I don't think it's a problem, it's defined as a TFPList and it's >> only >> ??? managed with methods DoAddDataModule and DoRemoveDataModule, >> which have >> ??? a TDataModule parameter. >> >> >> True. Besides, my patch does not help if the list contains garbage, >> meaning a TDataModule which was already freed. That is the most >> likely scenario. Why would you get a SIGSEGV otherwise? Such bugs are >> difficult to find. :( > > As I said, my suspicion was that a thread was calling DoAddDataModule > and/or DoRemoveDataModule, but I double checked and they're called by > the main thread. I'll triple check again. > It's also possible that I'm corrupting that data structure with some > stray pointer, but I couldn't reproduce it under the debugger, only on > the production machine. > Oh, well, I'll keep hunting for the cause. > I found the problem, though I don't know how to solve it: I'm using fpweb (actually my own subclass of TFPHTTPServerHandler) in threaded mode. When a request for a file comes in, it instantiates a TSimpleFileModule(*), which is derived from TDataModule and in turns it calls DoAddDataModule. The problem, as I suspected, is that a TFPList is not thread safe. Any hint?

FWIW, I implemented a thread safe version of TSimpleFileModule:

   TMyFileModule = class(TSimpleFileModule)
   private
     type
       TAsyncRequestData = class
         FRequest:TRequest;
         FResponse:TResponse;
         FEvent:TSimpleEvent;
         constructor Create(ARequest:TRequest; AResponse:TResponse);
         destructor Destroy;override;
       end;
     procedure AsyncHandleRequest(Data: PtrInt);
     class procedure HandleSimpleFileRequest(ARequest: TRequest;
AResponse: TResponse); static;
   public
     Class Procedure RegisterDefaultRoute;
   end;
procedure TMyFileModule.AsyncHandleRequest(Data: PtrInt);
var
   FileData: TAsyncRequestData;
begin
   FileData:=TAsyncRequestData(Data);
   with TSimpleFileModule.CreateNew(nil) do
   try
     HandleRequest(FileData.FRequest,FileData.FResponse)
   finally
     Free;
   end;
   FileData.FEvent.SetEvent;
end;
class procedure TMyFileModule.HandleSimpleFileRequest(ARequest: TRequest;
   AResponse: TResponse);
var
   FileData: TAsyncRequestData;
begin
   FileData:=TAsyncRequestData.Create(ARequest,AResponse);
   Application.QueueAsyncCall(@AsyncHandleRequest,PtrInt(FileData));
   FileData.FEvent.WaitFor(infinite);
   FileData.Free;
end;
class procedure TMyFileModule.RegisterDefaultRoute;
begin
   if BaseDir='' then
     BaseDir:=IncludeTrailingPathDelimiter(GetCurrentDir);
   httprouter.RegisterRoute('/*', at HandleSimpleFileRequest);
end;
constructor TMyFileModule.TAsyncRequestData.Create(ARequest: TRequest;
   AResponse: TResponse);
begin
   FRequest:=ARequest;
   FResponse:=AResponse;
   FEvent:=TSimpleEvent.Create;
end;
destructor TMyFileModule.TAsyncRequestData.Destroy;
begin
   FEvent.Free;
   inherited Destroy;
end;
Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Maxim Ganetsky
to Luca Olivetti

15.09.2025 22:47, Luca Olivetti via lazarus ?????:

Show quoted text 40 lines
El 15/9/25 a les 20:59, Luca Olivetti via lazarus ha escrit: > El 15/9/25 a les 20:35, Luca Olivetti via lazarus ha escrit: >> El 15/9/25 a les 20:17, Juha Manninen via lazarus ha escrit: >>> On Mon, Sep 15, 2025 at 9:09?PM Luca Olivetti via lazarus >>> < <mailto: >>> ide.org>> wrote: >>> >>> >>> ??? I don't think it's a problem, it's defined as a TFPList and >>> it's only >>> ??? managed with methods DoAddDataModule and DoRemoveDataModule, >>> which have >>> ??? a TDataModule parameter. >>> >>> >>> True. Besides, my patch does not help if the list contains garbage, >>> meaning a TDataModule which was already freed. That is the most >>> likely scenario. Why would you get a SIGSEGV otherwise? Such bugs >>> are difficult to find. :( >> >> As I said, my suspicion was that a thread was calling >> DoAddDataModule and/or DoRemoveDataModule, but I double checked and >> they're called by the main thread. I'll triple check again. >> It's also possible that I'm corrupting that data structure with some >> stray pointer, but I couldn't reproduce it under the debugger, only >> on the production machine. >> Oh, well, I'll keep hunting for the cause. >> > > > I found the problem, though I don't know how to solve it: I'm using > fpweb (actually my own subclass of TFPHTTPServerHandler) in threaded > mode. When a request for a file comes in, it instantiates a > TSimpleFileModule(*), which is derived from TDataModule and in turns > it calls DoAddDataModule. The problem, as I suspected, is that a > TFPList is not thread safe. > > Any hint? FWIW, I implemented a thread safe version of TSimpleFileModule:

Please report this to FPC issue tracker.

Best regards, Maxim Ganetsky mailto:

Reply by email

Michael Van Canneyt
to Maxim Ganetsky
Maxim Ganetsky wrote 5 lines
>> >> Any hint? > > FWIW, I implemented a thread safe version of TSimpleFileModule: Please report this to FPC issue tracker.

It is useless in FPC, since AsyncQueueCall exists only in Lazarus' TApplication class.

Secondly, the module is inherently thread safe if used correctly: When an instance of the module is created and destroyed per HTTP request. (ModuleKind = wkOneShot)

Michael.

Reply by email

zeljko
to Michael Van Canneyt
Michael Van Canneyt wrote 16 lines
On Tue, 16 Sep 2025, Maxim Ganetsky via lazarus wrote: >>> >>> Any hint? >> >> FWIW, I implemented a thread safe version of TSimpleFileModule: > Please report this to FPC issue tracker. It is useless in FPC, since AsyncQueueCall exists only in Lazarus' TApplication class. Secondly, the module is inherently thread safe if used correctly: When an instance of the module is created and destroyed per HTTP request. (ModuleKind = wkOneShot)

Note that I had segfault with sqldbrest (threaded) with gazzilion of connections and threads, so I had to override TSQLDBRestDBHandler and add constructor which creates class without Owner. used only in function TSQLDBRestDispatcher.CreateDBHandler(IO: TRestIO): TSQLDBRestDBHandler;so atm it is safe to create it without owner. Application is console app on linux64, so no gui to decoy.

If owner nil it crashes in
TSQLDBRestDispatcher.Notification(AComponent: TComponent; Operation: TOperation); after some time in threaded environment, that's what I remember but haven't enough time to investigate the case (gdb pointed me to Notification method). Something is definitelly wrong. Using fpc trunk, 2-3 months old.

zeljko

Reply by email

Luca Olivetti
to Michael Van Canneyt: It is useless in FPC, since AsyncQueueCall exists only in Lazarus' TApplication class.…

El 16/9/25 a les 9:14, Michael Van Canneyt via lazarus ha escrit:

Show quoted text 16 lines
On Tue, 16 Sep 2025, Maxim Ganetsky via lazarus wrote: >>> >>> Any hint? >> >> FWIW, I implemented a thread safe version of TSimpleFileModule: > Please report this to FPC issue tracker. It is useless in FPC, since AsyncQueueCall exists only in Lazarus' TApplication class. Secondly, the module is inherently thread safe if used correctly: When an instance of the module is created and destroyed per HTTP request. (ModuleKind = wkOneShot)

Define "used correctly".
Besides, how do I define wkOneShot since

  TSimpleFileModule.Kind:=wkOneShot;

gives the error

"Only class methods, class properties and class variables can be referred with class references"

?

Should I instantiate an instance of TSimpleFileModule beforehand (but in any case HandleSimpleFileRequest creates an instance)?

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Michael Van Canneyt
to Luca Olivetti
Luca Olivetti wrote 33 lines
El 16/9/25 a les 9:14, Michael Van Canneyt via lazarus ha escrit: > > > On Tue, 16 Sep 2025, Maxim Ganetsky via lazarus wrote: > >>>> >>>> Any hint? >>> >>> FWIW, I implemented a thread safe version of TSimpleFileModule: >> Please report this to FPC issue tracker. > > It is useless in FPC, since AsyncQueueCall exists only in Lazarus' > TApplication class. > > Secondly, the module is inherently thread safe if used correctly: When an > instance of the module is created and destroyed per HTTP request. > (ModuleKind = wkOneShot) Define "used correctly". Besides, how do I define wkOneShot since TSimpleFileModule.Kind:=wkOneShot; gives the error "Only class methods, class properties and class variables can be referred with class references" ? Should I instantiate an instance of TSimpleFileModule beforehand (but in any case HandleSimpleFileRequest creates an instance)?

Normally, you don't need to do anything, TSimpleFileModule already takes care of this:

constructor TFPCustomFileModule.CreateNew(AOwner: TComponent; CreateMode: Integer);
begin
   inherited CreateNew(aOwner,CreateMode);
   CacheControlMaxAge:=DefaultCacheControlMaxAge;
   Kind:=wkOneShot;
end;

(at least in trunk, I don't know what version you use)

Michael.

Reply by email

Luca Olivetti
to Michael Van Canneyt

El 16/9/25 a les 14:00, Michael Van Canneyt ha escrit:

Show quoted text 17 lines
> > Should I instantiate an instance of TSimpleFileModule beforehand (but > in any case HandleSimpleFileRequest creates an instance)? Normally, you don't need to do anything, TSimpleFileModule already takes care of this: constructor TFPCustomFileModule.CreateNew(AOwner: TComponent; CreateMode: Integer); begin ? inherited CreateNew(aOwner,CreateMode); ? CacheControlMaxAge:=DefaultCacheControlMaxAge; ? Kind:=wkOneShot; end; (at least in trunk, I don't know what version you use)

In 3.2.2 it's missing the "Kind:=wkOneShot" line, but I don't see how it makes it thread-safe: even in trunk
TSimpleFileModule.HandleSimpleFileRequest creates an instance of the class, do you mean that using wkOneShot that method is called in the context of the main thread?
I doubt it, I grepped the fcl-web directory and could not find any call to synchronize, but I could have missed it.
Though even if it was the case, I cannot use it with 3.2.2

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Michael Van Canneyt
to Luca Olivetti
Luca Olivetti wrote 25 lines
El 16/9/25 a les 14:00, Michael Van Canneyt ha escrit: >> >> Should I instantiate an instance of TSimpleFileModule beforehand (but >> in any case HandleSimpleFileRequest creates an instance)? > > Normally, you don't need to do anything, TSimpleFileModule already takes > care of this: > > constructor TFPCustomFileModule.CreateNew(AOwner: TComponent; > CreateMode: Integer); > begin > ? inherited CreateNew(aOwner,CreateMode); > ? CacheControlMaxAge:=DefaultCacheControlMaxAge; > ? Kind:=wkOneShot; > end; > > (at least in trunk, I don't know what version you use) > In 3.2.2 it's missing the "Kind:=wkOneShot" line, but I don't see how it makes it thread-safe: even in trunk TSimpleFileModule.HandleSimpleFileRequest creates an instance of the class, do you mean that using wkOneShot that method is called in the context of the main thread?

No.

It means that the module is created, sends the file and is destroyed. All needed data shared between threads is read-only only.

I doubt it, I grepped the fcl-web directory and could not find any call to synchronize, but I could have missed it.

But synchronize is not needed under normal operation ? Why do you need synchronize ?

Michael.

Reply by email

Luca Olivetti
to Michael Van Canneyt

El 16/9/25 a les 16:31, Michael Van Canneyt ha escrit:

Show quoted text 34 lines
On Tue, 16 Sep 2025, Luca Olivetti via lazarus wrote: > El 16/9/25 a les 14:00, Michael Van Canneyt ha escrit: > >>> >>> Should I instantiate an instance of TSimpleFileModule beforehand >>> (but in any case HandleSimpleFileRequest creates an instance)? >> >> Normally, you don't need to do anything, TSimpleFileModule already >> takes care of this: >> >> constructor TFPCustomFileModule.CreateNew(AOwner: TComponent; >> CreateMode: Integer); >> begin >> ?? inherited CreateNew(aOwner,CreateMode); >> ?? CacheControlMaxAge:=DefaultCacheControlMaxAge; >> ?? Kind:=wkOneShot; >> end; >> >> (at least in trunk, I don't know what version you use) >> > > In 3.2.2 it's missing the "Kind:=wkOneShot" line, but I don't see how > it makes it thread-safe: even in trunk > TSimpleFileModule.HandleSimpleFileRequest creates an instance of the > class, do you mean that using wkOneShot that method is called in the > context of the main thread? No. It means that the module is created, sends the file and is destroyed. All needed data shared between threads is read-only only.

Read my previous message: TSimpleFileModule is a descendant of TDataModule. When you create a TDataModule it calls AddDataModule, which (at least in an LCL application) is assigned to TScreen.DoAddDataModule

procedure TScreen.DoAddDataModule(DataModule: TDataModule);
begin
   FDataModuleList.Add(DataModule);
end;

FDataModuleList is a TFPList, which is not thread-safe (at least it isn't in fpc 3.2.2).

And when you destroy a TDataModule it calls

procedure TScreen.DoRemoveDataModule(DataModule: TDataModule);
begin
   FDataModuleList.Remove(DataModule);
end;
Show quoted text 6 lines
> I doubt it, I grepped the fcl-web directory and could not find any > call to synchronize, but I could have missed it. But synchronize is not needed under normal operation ? Why do you need synchronize ?

In order not to corrupt TScreen.FDataModulesList.
(Synchronize or, in my implementation, Application.QueueAsyncCall).

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Wayne Sherman
to Michael Van Canneyt: It is useless in FPC, since AsyncQueueCall exists only in Lazarus' TApplication class.…
Michael Van Canneyt wrote
Secondly, the module is inherently thread safe if used correctly: When an instance of the module is created and destroyed per HTTP request. (ModuleKind = wkOneShot)
Luca Olivetti wrote 7 lines
In 3.2.2 it's missing the "Kind:=wkOneShot" line, but I don't see how it makes it thread-safe: even in trunk TSimpleFileModule.HandleSimpleFileRequest creates an instance of the class, do you mean that using wkOneShot that method is called in the context of the main thread? I doubt it, I grepped the fcl-web directory and could not find any call to synchronize, but I could have missed it.

Assuming each HTTP request is run in its own thread, you create, use, and destroy the module from the request thread only. "Synchronize" is not needed because the main thread does not interact with the module.

Reply by email

Luca Olivetti
to Wayne Sherman

El 16/9/25 a les 16:42, Wayne Sherman via lazarus ha escrit:

Show quoted text 17 lines
Michael Van Canneyt wrote: > Secondly, the module is inherently thread safe if used correctly: > When an instance of the module is created and destroyed per HTTP request. > (ModuleKind = wkOneShot) Luca Olivetti wrote: > In 3.2.2 it's missing the "Kind:=wkOneShot" line, but I don't see how it > makes it thread-safe: even in trunk > TSimpleFileModule.HandleSimpleFileRequest creates an instance of the > class, do you mean that using wkOneShot that method is called in the > context of the main thread? > I doubt it, I grepped the fcl-web directory and could not find any call > to synchronize, but I could have missed it. Assuming each HTTP request is run in its own thread, you create, use, and destroy the module from the request thread only. "Synchronize" is not needed because the main thread does not interact with the module.

See my reply to Michael: in an LCL application a module modifies TScreen.FDataModuleList which is not thread-safe.

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email

Michael Van Canneyt
to Luca Olivetti: El 16/9/25 a les 16:31, Michael Van Canneyt ha escrit: Read my previous message:…
Luca Olivetti wrote 13 lines
>> it makes it thread-safe: even in trunk >> TSimpleFileModule.HandleSimpleFileRequest creates an instance of the >> class, do you mean that using wkOneShot that method is called in the >> context of the main thread? > > No. > > It means that the module is created, sends the file and is destroyed. > All needed data shared between threads is read-only only. Read my previous message: TSimpleFileModule is a descendant of TDataModule. When you create a TDataModule it calls AddDataModule, which (at least in an LCL application) is assigned to TScreen.DoAddDataModule

Sorry, I didn't read the whole thread.
I intervened only because Maxim Ganetsky referred to FPC.

Show quoted text 29 lines
procedure TScreen.DoAddDataModule(DataModule: TDataModule); begin FDataModuleList.Add(DataModule); end; FDataModuleList is a TFPList, which is not thread-safe (at least it isn't in fpc 3.2.2). And when you destroy a TDataModule it calls procedure TScreen.DoRemoveDataModule(DataModule: TDataModule); begin FDataModuleList.Remove(DataModule); end; > >> I doubt it, I grepped the fcl-web directory and could not find any >> call to synchronize, but I could have missed it. > > But synchronize is not needed under normal operation ? > Why do you need synchronize ? In order not to corrupt TScreen.FDataModulesList. (Synchronize or, in my implementation, Application.QueueAsyncCall).

OK. But that is a problem in lazarus, not FPC.

The AddDataModule/RemoveDataModule are callbacks that are installed by Lazarus' LCL. These callbacks need to be made threadsafe, that's all.

if you don't use the LCL, then there is no issue...

Michael.

Reply by email

Luca Olivetti
to Michael Van Canneyt

El 16/9/25 a les 17:43, Michael Van Canneyt via lazarus ha escrit:

Show quoted text 6 lines
OK. But that is a problem in lazarus, not FPC. The AddDataModule/RemoveDataModule are callbacks that are installed by Lazarus' LCL. These callbacks need to be made threadsafe, that's all. if you don't use the LCL, then there is no issue...

Yes, I'm using the LCL, I reported the bug here
https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/41832

Luca Olivetti Tel. +34 935883004 Ext. 3010 https://wetron.es https://wecobots.com

Reply by email