Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

In an event loop error does not terminate the program

35 views
Skip to first unread message

Cecil Westerhof

unread,
Jan 9, 2018, 4:44:06 AM1/9/18
to
Maybe it is intended functionality, but it caught me by surprise: when
in an event loop error does not terminate the program.

I have the following code:
#!/usr/bin/env tclsh


proc displayMessage {message} {
puts [format "%s: %s" [clock format [clock seconds] -format %T] ${message}]
}

proc generateError {} {
puts "Generating an error to show problem."
error "Does not terminate when there is an event loop"
}

proc loopDisplayMessage {} {
displayMessage "Just some text to show problem"
after [expr {15 * 1000}] loopDisplayMessage
}

loopDisplayMessage
after [expr {60 * 1000}] generateError
vwait forever

And this gives:
10:29:42: Just some text to show problem
10:29:57: Just some text to show problem
10:30:12: Just some text to show problem
10:30:27: Just some text to show problem
Generating an error to show problem.
Does not terminate when there is an event loop
while executing
"error "Does not terminate when there is an event loop""
(procedure "generateError" line 3)
invoked from within
"generateError"
("after" script)
10:30:42: Just some text to show problem
10:30:57: Just some text to show problem
10:31:12: Just some text to show problem

So is this intended, or an bug?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

Brad Lanam

unread,
Jan 9, 2018, 5:41:11 AM1/9/18
to
That's a very interesting question.
I am quite certain it is intended.
But I don't know the details.

I know when my application crashes with an error, some
pieces may continue to work (like the clock as your example),
but in general, the application becomes unusable.

But I don't know if the treatment of internal errors
is different than the 'error' command (which I don't use).

Note that the 'generateError' command is run from an after
script at the global level and not from within any proc.
The error return doesn't isn't contained inside of anything,
so it doesn't affect much.

Try: generating an error inside of 'loopDisplayMessage' after N
messages have been displayed.

I am looking forward to the answers here.

Cecil Westerhof

unread,
Jan 9, 2018, 6:28:05 AM1/9/18
to
That was what original was happening: I only tried to make the example
a bit simpler.

But when using:
#!/usr/bin/env tclsh


proc displayMessage {message} {
puts [format "%s: %s" [clock format [clock seconds] -format %T] ${message}]
}

proc loopDisplayMessage {} {
global counter

displayMessage "Just some text to show problem"
expr {31 / ${counter}}
incr counter -1
after [expr {15 * 1000}] loopDisplayMessage
}

set counter 4
loopDisplayMessage
vwait forever

I get:
12:18:25: Just some text to show problem
12:18:40: Just some text to show problem
12:18:55: Just some text to show problem
12:19:10: Just some text to show problem
12:19:25: Just some text to show problem
divide by zero
while executing
"expr {31 / ${counter}}"
(procedure "loopDisplayMessage" line 5)
invoked from within
"loopDisplayMessage"
("after" script)

And the script is still running, but will never do anything again.
:'-(


By the way would it not be better to terminate a program with an error
when there is an event loop, but no event waiting? Because that
program will never do anything again. So I would see that as an error.

Cecil Westerhof

unread,
Jan 9, 2018, 7:14:06 AM1/9/18
to
Even exit does not work. If I use:
proc loopDisplayMessage {} {
global counter

if {[catch {
displayMessage "Just some text to show problem"
expr {31 / ${counter}}
incr counter -1
after [expr {15 * 1000}] loopDisplayMessage
} errorMsg]} {
puts stderr ${::errorInfo}
exit ${::errorCode}
}

}

I get:
13:08:04: Just some text to show problem
13:08:19: Just some text to show problem
13:08:34: Just some text to show problem
13:08:49: Just some text to show problem
13:09:04: Just some text to show problem
divide by zero
while executing
"expr {31 / ${counter}}"
expected integer but got "ARITH DIVZERO {divide by zero}"
while executing
"exit ${::errorCode}"
(procedure "loopDisplayMessage" line 11)
invoked from within
"loopDisplayMessage"
("after" script)

And still the script does not terminate.

Arjen Markus

unread,
Jan 9, 2018, 7:28:56 AM1/9/18
to
On Tuesday, January 9, 2018 at 11:41:11 AM UTC+1, Brad Lanam wrote:

>
> I am looking forward to the answers here.

I am just guessing here, but the event loop is also used by Tk. If an error would indeed terminate the event loop any GUI running into an error would terminate as well. This is distinctly unwanted behaviour, as you would not be able to save your work. Even with the possibility that the user never sees the error message.

The side effect is that the event loop in Tcl-only programs also continues to work. So I conclude the behaviour is intentional.

But that is merely guessing ;).

Regards,

Arjen

Schelte Bron

unread,
Jan 9, 2018, 7:38:35 AM1/9/18
to
Cecil Westerhof wrote:
> Maybe it is intended functionality, but it caught me by surprise:
> when in an event loop error does not terminate the program.
>
This is intended. Not every error is necessarily fatal. But if you
don't like how Tcl handles background errors, you can use the
available tools to change the behaviour.

Add this to your code and the program will terminate whenever an
uncaught error happens:

proc fatal {msg info} {
puts stderr [dict get $info -errorinfo]
exit 255
}

interp bgerror {} fatal


Schelte.

Schelte Bron

unread,
Jan 9, 2018, 7:47:15 AM1/9/18
to
Cecil Westerhof wrote:
> And still the script does not terminate.

That's because you have an error in your exit command, as the script
reports:

expected integer but got "ARITH DIVZERO {divide by zero}"
while executing
"exit ${::errorCode}"

Try providing an integer argument, as exit expects.


Schelte.

Cecil Westerhof

unread,
Jan 9, 2018, 8:14:05 AM1/9/18
to
If that would be the case, I would say: do not use the same event loop
for tcl and tk.

Cecil Westerhof

unread,
Jan 9, 2018, 8:14:05 AM1/9/18
to
Oops, my bad. I expected errorCode to be an integer.

But Schelte explained why an error does not terminate an event loop
and what to do about it.

Cecil Westerhof

unread,
Jan 9, 2018, 8:14:05 AM1/9/18
to
Thanks: that works like a charm.

Just have to be careful then when using an event loop.

Cecil Westerhof

unread,
Jan 9, 2018, 8:44:05 AM1/9/18
to
Could I use:
exit [dict get $info -code]

Or is it not guaranteed that this is a (non zero) integer?

Arjen Markus

unread,
Jan 9, 2018, 9:13:56 AM1/9/18
to
On Tuesday, January 9, 2018 at 2:44:05 PM UTC+1, Cecil Westerhof wrote:
> Schelte Bron writes:
>
> > Cecil Westerhof wrote:
> >> Maybe it is intended functionality, but it caught me by surprise:
> >> when in an event loop error does not terminate the program.
> >>
> > This is intended. Not every error is necessarily fatal. But if you
> > don't like how Tcl handles background errors, you can use the
> > available tools to change the behaviour.
> >
> > Add this to your code and the program will terminate whenever an
> > uncaught error happens:
> >
> > proc fatal {msg info} {
> > puts stderr [dict get $info -errorinfo]
> > exit 255
> > }
>
> Could I use:
> exit [dict get $info -code]
>
> Or is it not guaranteed that this is a (non zero) integer?
>

To be sure, you could use:

exit [expr {[string is integer [dict get $info -code]]? [dict get $info -code] : 111}]

You will probably want to put that in a small proc ;)

Regards,

Arjen

Cecil Westerhof

unread,
Jan 9, 2018, 9:14:05 AM1/9/18
to
Cecil Westerhof <Ce...@decebal.nl> writes:

> Schelte Bron <nos...@wanadoo.nl> writes:
>
>> Cecil Westerhof wrote:
>>> Maybe it is intended functionality, but it caught me by surprise:
>>> when in an event loop error does not terminate the program.
>>>
>> This is intended. Not every error is necessarily fatal. But if you
>> don't like how Tcl handles background errors, you can use the
>> available tools to change the behaviour.
>>
>> Add this to your code and the program will terminate whenever an
>> uncaught error happens:
>>
>> proc fatal {msg info} {
>> puts stderr [dict get $info -errorinfo]
>> exit 255
>> }
>>
>> interp bgerror {} fatal
>
> Thanks: that works like a charm.
>
> Just have to be careful then when using an event loop.

Created a proc startEventLoop that default does this.

Cecil Westerhof

unread,
Jan 9, 2018, 10:44:07 AM1/9/18
to
I am using:
# Internal function used by startEventLoop
proc ::dcblUtilities::fatal {msg info} {
set error [dict get ${info} -code]
if {[expr {[string is integer ${error}]}]} {
set errorCode ${error}
} else {
puts stderr "${error} is not an interger"
set errorCode 255
}
puts stderr [dict get ${info} -errorinfo]
exit ${errorCode}
}

I added the puts because I like to see if it can be something else as
an integer.

Gerald Lester

unread,
Jan 9, 2018, 10:48:33 AM1/9/18
to
On 01/09/2018 07:02 AM, Cecil Westerhof wrote:
> Arjen Markus <arjen.m...@gmail.com> writes:
>
>> On Tuesday, January 9, 2018 at 11:41:11 AM UTC+1, Brad Lanam wrote:
>>
>>>
>>> I am looking forward to the answers here.
>>
>> I am just guessing here, but the event loop is also used by Tk. If an
>> error would indeed terminate the event loop any GUI running into an
>> error would terminate as well. This is distinctly unwanted behaviour, as
>> you would not be able to save your work. Even with the possibility that
>> the user never sees the error message.
>>
>> The side effect is that the event loop in Tcl-only programs also
>> continues to work. So I conclude the behaviour is intentional.
>>
>> But that is merely guessing ;).
>
> If that would be the case, I would say: do not use the same event loop
> for tcl and tk.
>

There is only one event loop in Tcl/Tk -- attempting to use more than
one event loop in a thread/program is a recipe for a very quick and
large disaster!

--
+----------------------------------------------------------------------+
| Gerald W. Lester, President, KNG Consulting LLC |
| Email: Gerald...@kng-consulting.net |
+----------------------------------------------------------------------+

Cecil Westerhof

unread,
Jan 9, 2018, 11:28:07 AM1/9/18
to
Gerald Lester <Gerald...@KnG-Consulting.net> writes:

> On 01/09/2018 07:02 AM, Cecil Westerhof wrote:
>> Arjen Markus <arjen.m...@gmail.com> writes:
>>
>>> On Tuesday, January 9, 2018 at 11:41:11 AM UTC+1, Brad Lanam wrote:
>>>
>>>>
>>>> I am looking forward to the answers here.
>>>
>>> I am just guessing here, but the event loop is also used by Tk. If an
>>> error would indeed terminate the event loop any GUI running into an
>>> error would terminate as well. This is distinctly unwanted behaviour, as
>>> you would not be able to save your work. Even with the possibility that
>>> the user never sees the error message.
>>>
>>> The side effect is that the event loop in Tcl-only programs also
>>> continues to work. So I conclude the behaviour is intentional.
>>>
>>> But that is merely guessing ;).
>>
>> If that would be the case, I would say: do not use the same event loop
>> for tcl and tk.
>>
>
> There is only one event loop in Tcl/Tk -- attempting to use more than
> one event loop in a thread/program is a recipe for a very quick and
> large disaster!

I did not mean to use two event loops, but to use different
implementations depending on if you use tk, or not. But I already
found a workaround.
0 new messages