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 ?
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
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
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
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 |
|______________________________________________________________________|
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.
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 |
+------------------------------------------------------------------------+
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'
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
I think he means a serial line ("RS" for "RS-232"). Which is
unfortunate; they're quite awkward to simulate with anything else.
Donal.
Yes that's it, but I use a synchonous RS-422 which is similar.