Delphi VCL sample locks up when using "Read using an Event"

Professional CAN and CAN FD Development Package for Windows®
Post Reply
dummzeuch
Posts: 4
Joined: Fri 5. Mar 2021, 15:54

Delphi VCL sample locks up when using "Read using an Event"

Post by dummzeuch » Fri 5. Mar 2021, 17:11

I have just compiled the Delphi VCL sample provided with PCAN-Developer 4 and tried it.
When I select "Read using an Event" on the "Messages" tab, the program locks up after a while.

That's because the VCL thread is waiting in the System.MonitorEnter call in RefreshMessages for access to the FReceivedMessages list which is blocked by the receiving thread. The receiving thread at the same time tries to write a status message which calls (via ProcessStatus -> ShowError -> TextOutput) TThread.Synchronize, which tries to switch to the VCL thread in order to access the VCL. Unfortunately that thread is already blocked while waiting in System.MonitorEnter. -> classical deadlock

My setup is special because it causes a lot "BUSWARNING" messages to be sent, so the deadlock might happen a lot more often than in other settings.

dummzeuch
Posts: 4
Joined: Fri 5. Mar 2021, 15:54

Re: Delphi VCL sample locks up when using "Read using an Event"

Post by dummzeuch » Fri 5. Mar 2021, 17:43

A workaround is to pass a timeout to the MonitorEnter call in RefreshMessages, like this:

Code: Select all

procedure TMainForm.RefreshMessages;
var
  msg: TCanMessage;
  Item: TListItem;
begin
  if System.MonitorEnter(FReceivedMessages, 100) then begin
    try
      for msg in FReceivedMessages do begin
        Item := FindMessageInListView(msg);
        if Assigned(Item) then
          RefreshExistingMessage(Item, msg)
        else
          AddNewMessage(msg);
      end;
    finally
      System.MonitorExit(FReceivedMessages);
    end;
  end;
end;
A better solution is to change ReadMessages so it takes a copy of the status message(*1), calls MonitorExit and only then passes the copy of the message to ProcesssStatus. But I haven't understood the code well enough yet to provide a possible implementation for this.

(*1: I just realized that the same problem exists for BusLoad messages: ProcessBusLoad also calls TextOutput which will end up calling TThreadSynchronize and cause the deadlock.)

K.Wolf
Software Development
Software Development
Posts: 141
Joined: Wed 22. Sep 2010, 15:37

Re: Delphi VCL sample locks up when using "Read using an Event"

Post by K.Wolf » Mon 8. Mar 2021, 11:14

Thank you for bringing this to our attention.
A simple solution to avoid a deadlock is to use TThread.Queue instead of TThread.Synchronize in the TMainForm.TextOutput function.

Post Reply