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

simulating a broken pipe scenario between a Tcl script and a C program

611 views
Skip to first unread message

Ravikanth

unread,
Jul 16, 2008, 1:41:09 AM7/16/08
to
Hi all,

I need to simulate a broken pipe scenario between a Tcl script and a
'C program..
For which i have written the following code

C program 'ctcl.c'
#include<stdio.h>
#include<string.h>
int main()
{
int i; char c[30],tmp[50];;
printf("Reading...\n");
fflush(stdout);
gets(c);
sprintf(tmp,"kill -9 %d",getpid());
printf("Killing....");
system(tmp);
printf("String written is :%s \n",c);
fflush(stdout);
return 0;
}

The Tcl Script is 'ctcl.tcl'

#!/usr/add-on/exptools/bin/tclsh

set fd [open "|./ctcl" r+]
puts "......................."
gets $fd tmp1
puts "#######################"
puts "tmp1 = $tmp1"
set stat 0
set tmp2 "Default value... "
if { ![catch { puts $fd "This is test.." } res]} {
if { ![catch { flush $fd } res] } {
if { ![catch { gets $fd tmp2} res ] } {
set stat 1
} else { puts "Error 'gets' from pipe : $res" }
} else { puts "Error 'flush' from pipe:$res " }
} else { puts "Error 'puts' from pipe:$res " }


if { $stat == 1 } {
puts "Success......:$tmp2 :)"
} else {
puts "Failure......:$tmp2 :("
}


Both these scripts reside in the same directory.
I have created an executable for 'C' program and then run the Tcl
script from command line.

o/p is as follows:-
.......................
#######################
tmp1 = Reading...
Success......: :)


What i was assuming about broken pipes is when two process are
communicating and when a pipe is established b/w both of them.. here
the case is tcl script communicating with a 'C' executable, and
suddenly one of the entity comes down.. here in this case i am killing
the 'C' process by extracting its pid.
Tcl script must report a broken pipe error as the pipe b/w both of
them is broken due to the 'C' process being killed.

But here my Tcl script is not catching that error.
Instead it is saying it was succesfull.. bt reading nothing from the
stream..

This is not my desired output. I need to simulate the error condition
of broken pipe..
Could any body help me modifying my program to simulate the error
scenario..

Thanks in advance,
Ravikanth

wiede...@googlemail.com

unread,
Jul 16, 2008, 2:35:31 AM7/16/08
to
SIGPIPE is sent to the writer side!
The reader side gets EOF.

uwe

Ravikanth

unread,
Jul 16, 2008, 2:48:27 AM7/16/08
to
On Jul 16, 11:35 am, "wiederl...@googlemail.com"

I have modifyed my 'C' program as below.. but still i find the same
response..

#include<stdio.h>
#include<signal.h>


#include<string.h>
int main()
{
int i; char c[30],tmp[50];;
printf("Reading...\n");
fflush(stdout);
gets(c);

printf("Killing using SIGPIPE...\n");
kill(getpid(),SIGPIPE);


printf("String written is :%s \n",c);
fflush(stdout);
return 0;
}

But the output of the Tcl script remains the same...No change in the
response..


wiede...@googlemail.com

unread,
Jul 16, 2008, 2:55:48 AM7/16/08
to
Write the two scripts into files and run
sigpipe.tcl

<sigpipe.tcl>
#!/usr/bin/tclsh

package require Tclx

signal trap SIGPIPE {puts SIGPIPE}

set pfd [ open "|./downstream.tcl" w ]

fconfigure $pfd -buffering line

while 1 {
puts $pfd hallo
puts hallo
after 500 set cont 1
vwait cont
}

<downstream.tcl>
#!/usr/bin/tclsh

package require Tclx

close stdin

puts stderr downstream:ready

after 5000 set cont
vwait cont
puts downstream:exit
exit

uwe

wiede...@googlemail.com

unread,
Jul 16, 2008, 3:00:19 AM7/16/08
to
On Jul 16, 8:48 am, Ravikanth <rkanth....@gmail.com> wrote:
> On Jul 16, 11:35 am, "wiederl...@googlemail.com"
>
> <wiederl...@googlemail.com> wrote:
> > SIGPIPE is sent to the writer side!
> > The reader side gets EOF.
>
> > uwe
>
> I have modifyed my 'C' program as below.. but still i find the same
> response..

The default action for SIGPIPE is to die.
see "man 7 signal" which gives all signames
and default behaviour.

uwe

Ravikanth

unread,
Jul 16, 2008, 3:23:18 AM7/16/08
to
On Jul 16, 12:00 pm, "wiederl...@googlemail.com"

Hi uwe,

I couldn't understand the code you have given.
I am new to Tcl & UNIX.
Could you please explain me what your program does.

Thanks in advance,

Raviknath

wiede...@googlemail.com

unread,
Jul 16, 2008, 4:55:51 AM7/16/08
to
Hi,
the default action for SIGPIPE ( i.e. writing
on a FILE handle without a listener on the other
end ) is to terminate the process.

To show the action we have to change this
to something that gives some diagnostic.

In tcl having a "|" as the first element of a
filename to open will create a process with
the rest of the filename as a command line
and hang it on a pipe connected to stdin for write,
stdout for read or both for read/write.


write both scripts to the same directory.
then
chmod u+x sigpipe.tcl downstream.tcl
<file sigpipe.tcl>
#!/usr/bin/tclsh
# get the Tclx extension for signal handling
package require Tclx

# change signal action for SIGPIPE:
# from the default "terminate process" to execute
# the script "puts SIGPIPE"


signal trap SIGPIPE {puts SIGPIPE}

# open a writing pipe to a process that executes
# the second script:


set pfd [ open "|./downstream.tcl" w ]

# see that each line get written to this pipe
# immediately ( and not in the 4k blocks that
# the default blocking size for nontty files )
fconfigure $pfd -buffering line

# do an endless loop:
while 1 {
# write "hallo" to the previously opened pipe
puts $pfd hallo
# write the same to stdout ( to see what happens )
puts hallo
# wait 500ms with the eventloop active


after 500 set cont 1
vwait cont
}

the second script
<file downstream.tcl>
#!/usr/bin/tclsh
# from copying sigpipe.tcl ;-)
package require Tclx

# close stdin to show SIGPIPE effects
# the upstream process has no "taker" now
close stdin

# debug : setup done, waiting.
puts stderr downstream:ready

# wait for 5 seconds while the eventloop is active


after 5000 set cont
vwait cont

# debug : exiting
puts downstream:exit
# and killing the process via exit
# actually the same would happen without the exit
exit

uwe

Ralf Fassel

unread,
Jul 16, 2008, 6:07:10 AM7/16/08
to
* Ravikanth <rkant...@gmail.com>

| Tcl script must report a broken pipe error as the pipe b/w both of
| them is broken due to the 'C' process being killed.
|
| But here my Tcl script is not catching that error. Instead it is
| saying it was succesfull.. bt reading nothing from the stream..

This is the expected behaviour. 'gets' simply gets EOF.

Only when you 'close' the channel, you will see the non-zero exit
status of the C-Program due to getting killed.

| This is not my desired output. I need to simulate the error
| condition of broken pipe..

Simply close that channel, and write in the exec'd program.
t.c
#include <stdio.h>
int main() {
if (printf("hello world\n") < 0) {
perror("printf");
}
if (EOF == fflush(stdout)) {
perror("fflush");
}
return 0;
}
cc -o t t.c

TCL:
tclsh% close [open "|./t" r]
=> child killed: write on pipe with no readers
tclsh% set errorCode
CHILDKILLED 25296 SIGPIPE {write on pipe with no readers}

Note that on Windows things behave differently: programs are not
signalled there, but simply get an EPIPE (or the windows equivalent)
error in the fflush().

$ cl -nologo -o t t.c
t.c
$ tclsh
% exec ./t.exe
hello world
% close [open "|./t.exe" r]
fflush: Invalid argument
% set errorCode
NONE

HTH
R'

Ravikanth

unread,
Jul 18, 2008, 5:02:27 AM7/18/08
to
On Jul 16, 3:07 pm, Ralf Fassel <ralf...@gmx.de> wrote:
> * Ravikanth <rkanth....@gmail.com>

Thank you all,
I understood the concept of pipe clearly from the discussion above..
My program is working fine now.

0 new messages