couldn't create pipe: too many open files

  • Follow


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)

Similiar Articles:













7/22/2012 9:15:13 AM


Reply: