For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > September 2005 > 2 Pipes between a child and parent process









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author 2 Pipes between a child and parent process
BenGoudey@myrealbox.com

2005-09-25, 3:58 am

I'm trying to write a program that has some data it wants to send
through a filter program(in this case tr), and then recieve the output
from that filter program. The way I'm trying to do it is by setting up
two pipes between the programs and piping the data in through one pipe
and back out through the other one. However all it does at the minute
is hang (I think) waiting for input from stdin but I can't figure out
why. I'm guessing that the child process must not be getting sent any
data but I don't how know how to fix it.

Here is the code:
int main (void)
{
pid_t pid;
int in_pipe[2];
int out_pipe[2];
char buffer[800];

/* Create the pipe. */
pipe (in_pipe);
pipe (out_pipe);

/* Create the child process. */
pid = vfork ();
if (pid == (pid_t) 0) /* child 1 */
{
/*close unneeded*/
close(in_pipe[1]);
close(out_pipe[0]);

/*Make pipes the stdin and stdout*/
dup2(in_pipe[0], 0);
close(in_pipe[0]);
dup2(out_pipe[1], 1);
close(out_pipe[1]);

/*change a to b*/
execl("/bin/tr", "tr", "a", "b" , 0);
perror("exec prog1");
exit(1);
}
else /*parent*/
{
/*close unneeded*/
close(in_pipe[0]);
close(out_pipe[1]);
/*write to and then read from child*/
write(in_pipe[1], "This is the data\n", 14);
read(out_pipe[0], buffer, sizeof(buffer));

/*send EOF to child*/
close(in_pipe[1]);
/*wait for end then close other end of pipe*/
waitpid(pid, NULL, 0);
close(out_pipe[0]);
return EXIT_SUCCESS;
}
}
Cheers for any help.
Ben Goudey

Pascal Bourguignon

2005-09-25, 3:58 am

BenGoudey@myrealbox.com writes:

> I'm trying to write a program that has some data it wants to send
> through a filter program(in this case tr), and then recieve the output
> from that filter program. The way I'm trying to do it is by setting up
> two pipes between the programs and piping the data in through one pipe
> and back out through the other one. However all it does at the minute
> is hang (I think) waiting for input from stdin but I can't figure out
> why. I'm guessing that the child process must not be getting sent any
> data but I don't how know how to fix it.
> [...]
> write(in_pipe[1], "This is the data\n", 14);


So the system puts 14 bytes into the pipe's buffer.

> read(out_pipe[0], buffer, sizeof(buffer));


and then your program blocks waiting on the other pipe.

> [...]


In the mean time, the buffered input layer (stdio) in tr is waiting to
fill a bufferfull of data before doing anything.


Either you fetch the sources of tr to see what buffer size it uses and
you send more than that, or close the pipe once you're done, or use
another program than tr.

write(in_pipe[1], "This is the data\n", 14);
close(in_pipe[1]); /* no more data */
read(out_pipe[0], buffer, sizeof(buffer));

Instead of read, you could use select (or poll) to see if there's data
available from the out_pipe[0], and not call read until there is. Of
course, tr won't send anything util you fill a buffer or close
in_pipe[1], so select will go on timing out, but at least you won't
deadlock.

--
__Pascal Bourguignon__ http://www.informatimago.com/
Small brave carnivores
Kill pine cones and mosquitoes
Fear vacuum cleaner
BenGoudey@myrealbox.com

2005-09-25, 3:58 am

That fixed it up nicely. Thanks for the help

Cheers
Ben Goudey

Gordon Burditt

2005-09-25, 3:58 am

>I'm trying to write a program that has some data it wants to send
>through a filter program(in this case tr), and then recieve the output
>from that filter program. The way I'm trying to do it is by setting up
>two pipes between the programs and piping the data in through one pipe
>and back out through the other one. However all it does at the minute
>is hang (I think) waiting for input from stdin but I can't figure out
>why. I'm guessing that the child process must not be getting sent any
>data but I don't how know how to fix it.


Think about stdio buffering (which tr probably uses) and deadlock.
You can end up with the child wanting more input while the parent
is waiting for output from the child. Or you can end up with the
parent trying to send more to the child while the child is trying
to send more to the parent.

The ways around it include:

(1) Re-write the child to use unbuffered I/O. (Often not possible because
you don't have source code to the child or you don't get to choose
it because the user does at runtime).
(2) Use non-blocking I/O (select or poll) to monitor both the
incoming and outgoing pipes.
(3) Use the suck() call on the read end of the pipe to force the child on
the write end of the pipe to call fflush() by threatening it
with violence or damage to its credit rating. This approach has
the divantage that there are no known implementations that have
ever worked, even once, but a number of programs seem to depend on
its existing.
(4) Fake out the child into using unbuffered I/O, say, by making
stdin and stdout a pty instead of a pipe.
(5) Ask the child to use unbuffered I/O. (e.g. tee -u, on systems where
the -u option exists)
(5) Use a protocol that eliminates deadlock, for example, sort programs
do not produce any output until after they have read EOF on input.

Gordon L. Burditt
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com