Recent

Author Topic: Timer event handler reentrancy  (Read 371 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 711
Timer event handler reentrancy
« on: February 26, 2020, 05:56:36 pm »
Are timer event handlers protected from reentry, or is it good practice to disable the timer at the head of a handler if there is even a slight risk that it might overrun the timer interval?

In the current case I'm using gtk2 on a KDE desktop, but from my POV if there were /any/ widget set that didn't implicitly protect against reentry it would be worth doing it explicitly.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

lucamar

  • Hero Member
  • *****
  • Posts: 2589
Re: Timer event handler reentrancy
« Reply #1 on: February 26, 2020, 06:22:21 pm »
Are timer event handlers protected from reentry, or is it good practice to disable the timer at the head of a handler if there is even a slight risk that it might overrun the timer interval?

IIRC (and I might not), they are not protected; but even if they were, stopping them on entry to the handler would still be good practice, and most of all for very short-interval timers.

Of course, if your timer fires once an hour (and the handler doesn't interact with the user!), stopping it might a little excessive :D
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

MarkMLl

  • Hero Member
  • *****
  • Posts: 711
Re: Timer event handler reentrancy
« Reply #2 on: February 26, 2020, 06:38:45 pm »
Thanks for that. Unless anybody can say that they are /definitely/ disabled (on all widget sets and OSes, and that this will never change), I agree that it's better to err on the side of caution.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

lucamar

  • Hero Member
  • *****
  • Posts: 2589
Re: Timer event handler reentrancy
« Reply #3 on: February 26, 2020, 06:46:25 pm »
I agree that it's better to err on the side of caution.

Indeed! My code is always choked full with tests for things that "can never happen" and "will never happen". We call those tests "Murphy-guards" :D
« Last Edit: February 26, 2020, 06:48:11 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

winni

  • Hero Member
  • *****
  • Posts: 1146
Re: Timer event handler reentrancy
« Reply #4 on: February 26, 2020, 07:04:46 pm »
Hi!

I use this code to prevent problems:

Code: Pascal  [Select]
  1. implementation
  2. var timerbusy : boolean= false;
  3. ...
  4. procedure TForm1.Timer1Timer(Sender:TObject);
  5. begin
  6. if timerbusy then exit;
  7. timerbusy := true;
  8. .....
  9. .....
  10. timerbusy := false;
  11. end;
  12.  
  13.  
  14.  

Winni





MarkMLl

  • Hero Member
  • *****
  • Posts: 711
Re: Timer event handler reentrancy
« Reply #5 on: February 26, 2020, 07:31:48 pm »
If you're doing that you should be protecting your  if ... := true;  with a critical section, or using InterlockedIncrement().

OK, so I agree that it's the main (GUI) thread and should only be revelling in the attentions of a single thread, but if protecting against the possibility that things go wrong it's worth doing things properly.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

lucamar

  • Hero Member
  • *****
  • Posts: 2589
Re: Timer event handler reentrancy
« Reply #6 on: February 26, 2020, 09:30:25 pm »
Winni, if you're worried to that point, wouldn't it be better (and more logical) to do what we're talking about, i.e.:

Code: Pascal  [Select]
  1. procedure TForm1.Timer1Timer(Sender:TObject);
  2. begin
  3.   (Sender as TTimer).Enabled := False;
  4.   try
  5.     {do your thing!}
  6.   finally
  7.     (Sender as TTimer).Enabled := True;
  8.   end;
  9. end;

I mean, you already have a boolean "variable" there, with the advantage that simply setting it to False will make the Timer stop firing the event!
« Last Edit: February 26, 2020, 09:32:42 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

ASerge

  • Hero Member
  • *****
  • Posts: 1498
Re: Timer event handler reentrancy
« Reply #7 on: February 26, 2020, 09:47:58 pm »
Are timer event handlers protected from reentry, or is it good practice to disable the timer at the head of a handler if there is even a slight risk that it might overrun the timer interval?
Since GUI event handlers are handled by a single thread, re-entry protection is only needed if the code inside the event calls waiting functions for other events that recursively call the current handler.

winni

  • Hero Member
  • *****
  • Posts: 1146
Re: Timer event handler reentrancy
« Reply #8 on: February 26, 2020, 09:59:14 pm »
Since GUI event handlers are handled by a single thread, re-entry protection is only needed if the code inside the event calls waiting functions for other events that recursively call the current handler.

I searched that in this clarity in the docs - in vain. That sentence should be put in the docs.

Thanx
Winni

MarkMLl

  • Hero Member
  • *****
  • Posts: 711
Re: Timer event handler reentrancy
« Reply #9 on: February 26, 2020, 10:16:43 pm »
Since GUI event handlers are handled by a single thread, re-entry protection is only needed if the code inside the event calls waiting functions for other events that recursively call the current handler.

I searched that in this clarity in the docs - in vain. That sentence should be put in the docs.

Thanx
Winni

Meaning no disrespect to anybody, but provided that it's accurate as far as all widget sets etc. are concerned. I remember catching PostMessage() reentering a few months ago, so I'm inclined towards caution.

The highly erratic bug that I've been keeping an eye open for over the last few days- rather than actively hunting- can only be caused (a) by a timer reentering or (b) by a shim invoked by Synchronize() having a similar effect. Both of them call a UDP broadcast at random intervals, into which I've inserted an explicit pacing delay if multiple broadcasts go to different subnets (because an obfuscated timestamp is in the message): and the delay is substantially longer than the timer interval.

A particular smoking gun is that I think I've seen form activity which can only be caused by the timer firing at the same time as an error dialog(ue) is on the screen... I'm not quite sure what to make of that one yet.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.