Bug? Timers fire even after being erased
6 posts
• Page 1 of 1
Bug? Timers fire even after being erased
I'm using Dyalog APL/W-64 Version 19.0.49048. I'm finding that in some circumstances Timers continue to fire even AFTER being erased. I would think that erasing a timer should remove the timer from the event queue. Explicitly setting the timers' Active property to 0 before erasing it solves the problem, but that shouldn't be necessary.
Define the function below. To run it, enter: foo 'Run'
The Timer will fire. The onTimer handler erases the Timer, but the Timer fires again and this time the program blows up because the Timer doesn't actually exist anymore. This seems like a bug to me.
Define the function below. To run it, enter: foo 'Run'
The Timer will fire. The onTimer handler erases the Timer, but the Timer fires again and this time the program blows up because the Timer doesn't actually exist anymore. This seems like a bug to me.
- Code: Select all
foo arg
⍝ Show that erasing a timer doesn't stop it from firing.
⍝ Using Dyalog APL/W-64 Version 19.0.49048
:IF arg≡'Run'
'timer' ⎕WC 'Timer' ('Interval' 1000) ('Event' 'onTimer' 'foo')
:ELSEIF 'Timer'≡2⊃arg
'' ⋄ 'Timer ',(⍕↑arg),' fired: ⎕NC of timer is: ',⎕NC ⍕↑arg
⎕CS 'timer' ⍝ Switch namespace to the timer (blows up the second time around).
'⎕NC of #.timer before ⎕EX: ',⍕⎕NC '#.timer'
'Namespace before ⎕EX of #.timer is: ',⍕⎕THIS
⍝ In a real program some stuff would happen here.
⍝⍝⍝ #.timer.Active←0 ⍝ This stops the problem, but it shouldn't be necessary.
⎕EX '#.timer' ⍝ Erase the timer.
'#.timer has been ERASED'
'⎕NC of #.timer after ⎕EX: ',⍕⎕NC '#.timer'
'Namespace after ⎕EX of #.timer is: ',⍕⎕THIS
⎕DQ ''
:ENDIF
- Rav
- Posts: 23
- Joined: Tue Jul 25, 2023 4:41 pm
Re: Bug? Timers fire even after being erased
Hi Ray!
I think the problem may be caused by changing space into the timer namespace. As long as you have code which is running "in" that namespace, the expunge will only remove the reference from to the space from the global name #.timer, but it cannot actually erase the timer namespace.
If I comment out the line with the ⎕CS, the timer only fires once.
Does this explain what you are seeing?
/ Morten
I think the problem may be caused by changing space into the timer namespace. As long as you have code which is running "in" that namespace, the expunge will only remove the reference from to the space from the global name #.timer, but it cannot actually erase the timer namespace.
If I comment out the line with the ⎕CS, the timer only fires once.
Does this explain what you are seeing?
/ Morten
-
Morten|Dyalog - Posts: 460
- Joined: Tue Sep 09, 2008 3:52 pm
Re: Bug? Timers fire even after being erased
Hi, Morten. Thanks for your quick reply. By the way, this is Rav, the APLer who worked with Brian B decades ago at STSC, not Ray (Cannon). I had a feeling that confusion might happen sometime, with "Rav" and "Ray" looking so much alike. At any rate ...
I understand your point about being "in" the timer namespace. It's sort of like erasing a running function right from within that function. The function continues to run even after it's been erased. I would point out though that even though the function is still running, it ACTS as if it was erased otherwise. For example:
Therefore I still think that, despite the fact that the code is running inside the (pending erased) namespace, it should ACT as if it was erased. The interpreter knows it is pending erasure (⎕NC returning 0 shows that), so it should be able to act as if it actually was erased (not fire the timer).
I agree that removing the call to ⎕CS "fixes" the problem. (By the way, the same issue happens if I surround that code using :WITH and :ENDWITH instead). But the reason I changed the namespace to the timer is that in my REAL application where this happened, the code is significantly more complex. There, the timer is actually owned by (a child of) a form. And it's the form that I was erasing, and therefore the timer was also erased. Before erasing the form I was making many references to children of that form, and didn't want to have to keep referring to it's children by prefacing their names with "form" (so I could refer to abc, def, and ghi rather than form.abc, form.def, and form.ghi). So In my real app, I was changing the namespace to the form.
I hope that explains things a little more. I look forward to your reply. / Rav
I understand your point about being "in" the timer namespace. It's sort of like erasing a running function right from within that function. The function continues to run even after it's been erased. I would point out though that even though the function is still running, it ACTS as if it was erased otherwise. For example:
- Code: Select all
foo
a←1
⎕EX 'foo'
b←2 ⍝ Defined AFTER foo is erased
'a is ',(⍕a),', b is ',⍕b
foo ⍝ Will (and should) produce a VALUE ERROR
- Code: Select all
foo
a is 1, b is 2
VALUE ERROR: Undefined name: foo
foo[5] foo
∧
Therefore I still think that, despite the fact that the code is running inside the (pending erased) namespace, it should ACT as if it was erased. The interpreter knows it is pending erasure (⎕NC returning 0 shows that), so it should be able to act as if it actually was erased (not fire the timer).
I agree that removing the call to ⎕CS "fixes" the problem. (By the way, the same issue happens if I surround that code using :WITH and :ENDWITH instead). But the reason I changed the namespace to the timer is that in my REAL application where this happened, the code is significantly more complex. There, the timer is actually owned by (a child of) a form. And it's the form that I was erasing, and therefore the timer was also erased. Before erasing the form I was making many references to children of that form, and didn't want to have to keep referring to it's children by prefacing their names with "form" (so I could refer to abc, def, and ghi rather than form.abc, form.def, and form.ghi). So In my real app, I was changing the namespace to the form.
I hope that explains things a little more. I look forward to your reply. / Rav
- Rav
- Posts: 23
- Joined: Tue Jul 25, 2023 4:41 pm
Re: Bug? Timers fire even after being erased
Hi Rav, sorry about my fading eyesight :)
I'm afraid I must disagree with you when you say it acts as if it has been erased. On the contrary, the timer is very much acting as if it exists, by continuing to fire events. Note that any namespace can have multiple references to it. For example, you could have two timers called Timer1 and Timer2, and a reference called CurrentTimer which was a reference to the timer that you were currently using. If CurrentTimer was pointing to Timer1 and you expunged 'Timer1', the reference from CurrentTimer would keep that timer alive. Objects only disappear properly when the LAST remaining reference is removed. So long as the current space is that namespace, this is a reference and will keep the object alive. The system doesn't keep track of which name or reference was the "original" one and treat that specially.
Asking for the timer to stop firing when the original name disappears seems a bit like wanting your function 'foo' to stop running after the line which expunges the name 'foo', and not execute the last three lines?
I'm afraid I must disagree with you when you say it acts as if it has been erased. On the contrary, the timer is very much acting as if it exists, by continuing to fire events. Note that any namespace can have multiple references to it. For example, you could have two timers called Timer1 and Timer2, and a reference called CurrentTimer which was a reference to the timer that you were currently using. If CurrentTimer was pointing to Timer1 and you expunged 'Timer1', the reference from CurrentTimer would keep that timer alive. Objects only disappear properly when the LAST remaining reference is removed. So long as the current space is that namespace, this is a reference and will keep the object alive. The system doesn't keep track of which name or reference was the "original" one and treat that specially.
Asking for the timer to stop firing when the original name disappears seems a bit like wanting your function 'foo' to stop running after the line which expunges the name 'foo', and not execute the last three lines?
-
Morten|Dyalog - Posts: 460
- Joined: Tue Sep 09, 2008 3:52 pm
Re: Bug? Timers fire even after being erased
Thanks, Morten. Although I find it a little disconcerting that something like a Timer that is pending erasure can still be Active, I think I see your point about other references to the same object, and that being "in" the namespace is such a reference. While the reference named "#.timer" has been erased, the object still exists because there is at least one other reference. I can easily deal with the issue by setting the Active property to 0 just prior to "erasing" it. Just wanted to make sure it wasn't a bug. / Rav
- Rav
- Posts: 23
- Joined: Tue Jul 25, 2023 4:41 pm
Re: Bug? Timers fire even after being erased
Thanks! As far as I can see, the system is behaving "as designed".
-
Morten|Dyalog - Posts: 460
- Joined: Tue Sep 09, 2008 3:52 pm
6 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group