#1 2024-10-24 18:38:14

zen010101
Member
Registered: 2024-06-15
Posts: 66

A strange error

In 31-WebSockets\Project31ChatServer.dpr, I try to use TSynObjectListLocked in TChatService to save the IChatCallback because I like to control the lock myself and will access certain global variables in the service in the future. But during the debugging process, I found that an AV error was generated when calling callback in TchatService.BlaBla. To be precise, it was an exception generated in FPC_INTF_ASSIGN.

The strange thing is that when I retain the original array of IChatCallback and register it with the Client, and also retain the InterfaceArrayAdd(f2,callback);, the program will not generate an AV exception. I really didn't understand the reason.

Here is the gist: https://gist.github.com/zen010101/87a35 … c211996889

Offline

#2 2024-10-24 18:58:33

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: A strange error

InterfaceArrayAdd() is not thread-safe.

Offline

#3 2024-10-24 19:14:33

zen010101
Member
Registered: 2024-06-15
Posts: 66

Re: A strange error

If the program has InterfaceArrayAdd(), then

intf := fConnected[i] 

will not report an error;
If you comment it out, an error will be reported.

Your explanation seems to be the exact opposite of what I stated.

Offline

#4 2024-10-24 19:16:58

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: A strange error

Ah now I understand.

TSynObjectListLocked is for TObject not interface.
As its name states.

Offline

#5 2024-10-25 09:32:01

zen010101
Member
Registered: 2024-06-15
Posts: 66

Re: A strange error

ab wrote:

TSynObjectListLocked is for TObject not interface.
As its name states.

Thank you for your reminder. By searching the source code, I feel that the TSynLogCallbacks object in mormot.core.log.pas is what I am looking for. I can refer to it to implement my own Callback Interface List.

However, I still feel strange, why does a certain statement in the following code "magically" avoid the AV exception ?

procedure TChatService.Join(const pseudo: string;
  const callback: IChatCallback);
begin
  if fConnected = nil then
    fConnected := TSynObjectListLocked.Create(false);  
  fConnected.Add(callback);
  InterfaceArrayAdd(f2,callback); // This statement magically avoids the AV exception generated by the `Intf := fConnected[i]` statement in the BlaBla Method below.
end;

Offline

#6 2024-10-25 16:35:44

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: A strange error

In fact, TSynObjectListLocked assign pointers, whereas InterfaceArrayAdd() assign interface, i.e. not only copy the pointer but call IInterface._Acquire which increment the instance refcount within the f2 list.
So there is no dangling pointer any more.

Note that with heavily multi threaded process, i.e. a lot of concurrent Join() then InterfaceArrayAdd() would start randomly trigger GPF because its internal f2 storage is not protected by a lock.

Offline

#7 2024-10-26 03:01:53

zen010101
Member
Registered: 2024-06-15
Posts: 66

Re: A strange error

ab wrote:

Note that with heavily multi threaded process, i.e. a lot of concurrent Join() then InterfaceArrayAdd() would start randomly trigger GPF because its internal f2 storage is not protected by a lock.

Even if optExecLockedPerInterface option is used when creating IChatService ?

    Server.ServiceDefine(TChatService,[IChatService],sicShared).
      SetOptions([],[optExecLockedPerInterface]). // thread-safe fConnected[]
      ByPassAuthentication := true;  

Offline

#8 2024-10-26 06:26:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,655
Website

Re: A strange error

optExecLockedPerInterface would make it thread-safe of course.

It is just not thread-safe by default, for performance reasons.

Offline

Board footer

Powered by FluxBB