TROEventReceiver.OnTimerTick is not thread safe

I’m using the named pipe channels with events, which means that there is polling done by TOREventReceiver because the channel is not event aware.
This is fine by me, but to make sure that all events are processed before closing the channel, I had to make sure FireEvents is called. The easiest way was to call TROEventReceiver.OnTimerTick which conveniently has the public visibility.
However, that method does not behave well when it is being called by a second thread while it is already running. This leads to various crashes later on, so I suspect some sort of memory corruption along the way.
I thus modified the code so that the second caller waits until the first has finished, like this:

while FProcessingTimerTick do
  Sleep(10);

eventsdata := nil;
FProcessingTimerTick := True;
try
  // existing code
finally
  FProcessingTimerTick := False;
  if (eventsdata<>nil)
    then eventsdata.Free;
end;

Of course FProcessingTimerTick is declared as a private field.
Using the code above, I no longer have the crashes while still receiving all the pending events. Initially, I wanted to pause the timer in my own code that calls OnTimerTick but I could not find an easy way to do so. In the end, having the method “defend” itself against parallel calls is easier on SDK users.

As a side note, the test if (eventsdata<>nil) before calling Free is useless, that’s exactly what Free does before calling Destroy.

if you set Interval to 0, it will stop internal timer. it is easier way to disable execution of events

Well, setting Interval calls SetTimeout on fTimer which has this code:

procedure TROThreadTimer.SetTimeout(const Value: integer);
begin
  if (Value<MinTimerMS) then
    fTimeoutMS := MinTimerMS
  else
    fTimeoutMS := Value;
  ResetTimer;
end;

So to me, it will use MinTimerMS which is 100, will only skip one run, but afterwards will use 100ms for its interval.

Did I miss something?

You are right, I forgot that we don’t use standard TTimer

Thanks, logged as bugs://80646

bugs://80646 got closed with status fixed.