|
|
couldn't create pipe: too many open files
Hello,
Due to learning TCL by "Effective TCL/Tk Programming" bok I've tried
to reproduce the buffering problem and solution described in chapter
7.4 "Working around buffering problems"(p.273)
I wrote and compile C program example:
========================================
#include <stdio.h>
main () {
while (1) {
printf ("This is a line of text which might be buffered!\n");
sleep (1);
}
}
=======================================
and tired to solve buffering problem by TCL script:
=======================================
#!/usr/bin/tclsh
while {1} {
set fid [open "| ./buffdemo " "r"]
fconfigure $fid -buffering none
fileevent $fid readable [list output_buffer $fid]
# puts $fid "This is a line of text which might be buffered. \n"
# puts $fid "So is this line"
# after 1
}
proc output_buffer { chan } {
if {[eof $chan]} {
puts stderr " Closing $chan "
catch {close $chan} res
return
}
set data [read $chan]
puts $data
}
========================================
Unfortunately this workaround is not working and I get the following
error:
../buffdemo.tcl
channel is not readable
while executing
"fileevent $fid readable [list output_buffer $fid]"
("while" body line 4)
invoked from within
"while {1} {
set fid [open "| cat " "w"]
fconfigure $fid -buffering line
fileevent $fid readable [list output_buffer $fid]
puts $fid "This is a lin..."
(file "./buffdemo.tcl" line 3)
I am using "Ubuntu 10.04.1 LTS" Linux 2.6.32-24-generic i686 GNU/
Linux
|
|
0
|
|
|
|
Reply
|
rkaganov
|
9/23/2010 7:39:28 AM |
|
* rkaganov <rkaganov@gmail.com>
| and tired to solve buffering problem by TCL script:
|
| =======================================
|
| #!/usr/bin/tclsh
|
| while {1} {
| set fid [open "| ./buffdemo " "r"]
You run the 'open' in a while loop which creates many many 'buffdemo'
processes until you hit the per-process-limit of the OS.
| fconfigure $fid -buffering none
Note that -buffering only affects output channels, not input channels.
The program which produces the output must set it's stdout to
non-buffering to obtain any effect. You could use fflush(stdout) after
the printf() in the main() program.
| proc output_buffer { chan } {
| if {[eof $chan]} {
| puts stderr " Closing $chan "
| catch {close $chan} res
| return
| }
| set data [read $chan]
| puts $data
| }
In order for that to work properly, the channel should be set to
-blocking 0 too, otherwise the 'read' will block until the input channel
is closed.
The wiki.tcl.tk has example code on fileevent usage,
eg http://wiki.tcl.tk/880
HTH
R'
|
|
0
|
|
|
|
Reply
|
ralfixx (1239)
|
9/23/2010 8:25:32 AM
|
|
On Sep 23, 12:39=A0am, rkaganov <rkaga...@gmail.com> wrote:
> Hello,
>
> Due to learning TCL by "Effective TCL/Tk Programming" bok I've tried
> to reproduce the buffering problem and solution described in chapter
> 7.4 "Working around buffering problems"(p.273)
>
> I wrote and compile C program example:
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> #include <stdio.h>
>
> main () {
> =A0 =A0 =A0 =A0 while (1) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printf ("This is a line of text which mig=
ht be buffered!\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sleep (1);
> =A0 =A0 =A0 =A0 }}
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> and tired to solve buffering problem by TCL script:
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> #!/usr/bin/tclsh
>
> while {1} {
> =A0 =A0 =A0 =A0 set fid [open "| ./buffdemo " "r"]
> =A0 =A0 =A0 =A0 fconfigure $fid -buffering none
> =A0 =A0 =A0 =A0 fileevent $fid readable [list output_buffer $fid]
> # =A0 =A0 =A0 puts $fid "This is a line of text which might be buffered. =
\n"
> # =A0 =A0 =A0 puts $fid "So is this line"
> # =A0 =A0 =A0 after 1
>
> }
>
> proc output_buffer { chan } {
> =A0 =A0 =A0 =A0 if {[eof $chan]} {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 puts stderr " Closing $chan "
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 catch {close $chan} res
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return
> =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 set data [read $chan]
> =A0 =A0 =A0 =A0 puts $data
>
> }
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> Unfortunately this workaround is not working and I get the following
> error:
>
> ./buffdemo.tcl
> channel is not readable
> =A0 =A0 while executing
> "fileevent $fid readable [list output_buffer $fid]"
> =A0 =A0 ("while" body line 4)
> =A0 =A0 invoked from within
> "while {1} {
> =A0 =A0 =A0 =A0 set fid [open "| cat " "w"]
> =A0 =A0 =A0 =A0 fconfigure $fid -buffering line
> =A0 =A0 =A0 =A0 fileevent $fid readable [list output_buffer $fid]
> =A0 =A0 =A0 =A0 puts $fid "This is a lin..."
> =A0 =A0 (file "./buffdemo.tcl" line 3)
Not sure what the buffering problem is exactly, but note a few things:
1. your error message contains different code than the code you say
you are using (r vs w).
2. as said by ralf, you are running in a loop for no obvious reason.
3. output_buffer is never defined, the [while] loop never stops.
Other things not apparent to most users of fconfigure options:
-buffering actually determines when to flush, i/o is always buffered
-buffersize could also be set to zero, but the effect isn't
necessarily important
But looking at page 273-5, I don't see your code in there at all.
Advice:
fconfigure $chan -buffering none -buffersize 0
One way to get a good idea of exactly how to configure a channel for
unbuffered output on you platform do:
% foconfigure stderr
|
|
0
|
|
|
|
Reply
|
tom.rmadilo (754)
|
9/23/2010 4:32:28 PM
|
|
On Sep 23, 1:25=A0am, Ralf Fassel <ralf...@gmx.de> wrote:
> * rkaganov <rkaga...@gmail.com>
> You run the 'open' in a while loop which creates many many 'buffdemo'
> processes until you hit the per-process-limit of the OS.
>
> | =A0 =A0 =A0 fconfigure $fid -buffering none
>
> Note that -buffering only affects output channels, not input channels.
Shoot, didn't notice you said this. -buffering only affects output
channels because it determines flushing conditions.
But looking again at the exact error message, this thread title is
misleading:
[filevent] failed because the channel isn't readable (as in it isn't
configured to ever be readable).
> channel is not readable
> while executing
> "fileevent $fid readable [list output_buffer $fid]"
That is just the first error in the code.
|
|
0
|
|
|
|
Reply
|
tom
|
9/23/2010 5:00:46 PM
|
|
|
3 Replies
661 Views
(page loaded in 0.064 seconds)
|
|
|
|
|
|
|
|
|