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

Using fileveent with a Tk GUI : "out of stack space (infinite loop?)"

339 views
Skip to first unread message

Thomas MENEZ

unread,
Sep 1, 2010, 7:00:37 AM9/1/10
to
Hello

Why does the following code yield this "out of stack" error ?

package require Tk
proc myCb { } {
update
}
button .b -text pushMeHard -command { fileevent $fileH readable
{ myCb } }
pack .b
set fileH [open existingFile.txt r]


I actually have a problem using fileevent on an opened file using a
TkGUI. As long as the file hasn't been totally read, the GUI
freezes...Is there any clean way to achieve this without freezing the
GUI ? Calling update in the myCb callback does not seem to solve my
issue ... Any suggestion ? Threads ?

Eric Boudaillier

unread,
Sep 1, 2010, 7:49:57 AM9/1/10
to
Hello,

Calling update in the fileevent IS your issue: this cause your
fileevent callback to be called again, and so on, until the stack is
full.

**never call update in filevent**

If not, it should be in the manual page.

-eric

Robert Heller

unread,
Sep 1, 2010, 7:57:46 AM9/1/10
to

1) Don't call update from an event handler! This is really, really bad.
This re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
re-enters the event loop, which will call the event handler, which
.. Opps, stack overflow!

2) Fileevents don't really make sense when dealing with a plain file.
Fileevents are really meant for almost anything *else*: pipes, sockets,
serial ports, etc. where data becomes asyncronously available or is
consumed asyncronously, eg by a another process or some other external
activity.

If you are reading a really long file and doing lots of processing of
its contents consider this:

set fileH [open existingFile.txt r]

while {[gets $fileH line] >= 0} {
process_line $line
update idle
}
close $fileH


>

--
Robert Heller -- Get the Deepwoods Software FireFox Toolbar!
Deepwoods Software -- Linux Installation and Administration
http://www.deepsoft.com/ -- Web Hosting, with CGI and Database
hel...@deepsoft.com -- Contract Programming: C/C++, Tcl/Tk


Uwe Klein

unread,
Sep 1, 2010, 8:17:50 AM9/1/10
to
[update] tries to flush all outstanding events.
the readable fileevent stays readable and is thus run until doomsday or
the recursion limit is reached ( inclusive of the recursive update ).

try this:

package require Tk
set countA 0
set countB 0
proc myCb { } {
global countA countB
incr countA
puts stderr MyCb:A:$countA:$countB
update
incr countB
puts stderr MyCb:B:i$countA:$countB


}
button .b -text pushMeHard -command {
fileevent $fileH readable { myCb }
}
pack .b
set fileH [open existingFile.txt r]

# end

compare to this:
package require Tk
set countA 0
set countB 0
proc myCb { } {
global fileH
global countA countB
incr countA
puts stderr MyCb:A:$countA:$countB
set script [ fileevent $fileH readable ]
fileevent $fileH readable {}
update
puts stderr [gets $fileH]
if {[eof $fileH]} {
close $fileH
puts stderr $fileH:EOF!
.b configure -bg red1
return
}
fileevent $fileH readable $script
incr countB
puts stderr MyCb:B:$countA:$countB


}
button .b -text pushMeHard -command {
fileevent $fileH readable { myCb }
}
pack .b

set fileH [open /etc/hosts r]
#end

using fileevent on an instantly accessible channel has its downsides.

uwe


Don Porter

unread,
Sep 1, 2010, 8:49:19 AM9/1/10
to
Robert Heller wrote:
> 2) Fileevents don't really make sense when dealing with a plain file.
> Fileevents are really meant for almost anything *else*:...

Which is a good reason to start calling them by their new name
[chan event]s.

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Thomas MENEZ

unread,
Sep 1, 2010, 8:50:01 AM9/1/10
to

Thanks for your suggestions. Why am I doing that ? I normally
fileveent an RS line. But, for test purposes when there is no unit
connected to the RS line, I use a "dump file" of what is sent by the
normally connected unit. This is like a simulation mode where I can
test my tcl parser. I have implemented a "simulation mode" in my tcl
app based on fileevent too to avoid diverting too much from the RS
nominal mode.
Maybe there is a clever way to use a "dump file" and fileevent ? I'm
thinking of a proc that would write inside a file every 1 seconds, and
I would fileevent the written file. What do you think ? That would
slow down the filevent callbacks, and I wouldn't even have to call
update.

Thomas MENEZ

unread,
Sep 1, 2010, 8:53:12 AM9/1/10
to
On Sep 1, 2:17 pm, Uwe Klein <uwe_klein_habertw...@t-online.de> wrote:

OK that looks good. Thanks !

Gerald W. Lester

unread,
Sep 1, 2010, 9:12:42 AM9/1/10
to

Have your main program open up a socket to listen on instead of an RS line.

Have a test driver read the dump and periodically (like every second) send
data (don't forget to flush).

Sockets behave much more like RS lines then a regular file.


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

Ralf Fassel

unread,
Sep 1, 2010, 9:17:11 AM9/1/10
to
* Thomas MENEZ <menez....@gmail.com>

| I normally fileveent an RS line.

What is an RS line?

| But, for test purposes when there is no unit connected to the RS line,

If this is for testing purposes, why don't you write a small 'writer'
script which spews out the file contents one line a second? Then in
your app open a pipe to that script and you should be able to use your
filevent code on that pipe channel.

Pseudo:
# writer:
fconfigure stdout -buffering line
set fd [open file r]
while {[gets $fd line] >= 0} {
puts $line
after 1000
}

# reader
set fd [open |writer r]
fileevent $fd readable myproc

=> myproc should get called one a second

HTH
R'

Uwe Klein

unread,
Sep 1, 2010, 10:12:29 AM9/1/10
to
Thomas MENEZ wrote:
> OK that looks good. Thanks !
Independent of my example and going by your reported setup:

I would go with the testgenerator approach given by Gerald above.

Write yourself a little app that emulates your data source in an acceptable
manner. Either as a socket server or using expect ( via (p)tty .)

Avoid tweaking your app for testing purposes.
Those tweaks usually tweak around bugs rendering them invisible too.

uwe

Donal K. Fellows

unread,
Sep 3, 2010, 10:39:03 AM9/3/10
to
On 1 Sep, 14:17, Ralf Fassel <ralf...@gmx.de> wrote:
> * Thomas MENEZ <menez.tho...@gmail.com>

> | I normally fileveent an RS line.
>
> What is an RS line?

I think he means a serial line ("RS" for "RS-232"). Which is
unfortunate; they're quite awkward to simulate with anything else.

Donal.

Thomas MENEZ

unread,
Sep 4, 2010, 8:44:16 AM9/4/10
to
On Sep 3, 4:39 pm, "Donal K. Fellows"

Yes that's it, but I use a synchonous RS-422 which is similar.

0 new messages