deadlock quiz (was: How to do a pipe & fork?)
Maarten Litmaath
maart at cs.vu.nl
Sat Nov 5 11:35:18 AEST 1988
\In article <Nov.2.14.51.36.1988.8260 at zztop.rutgers.edu>, pratt at zztop.rutgers.edu (Lorien Y. Pratt) writes:
\I have two processes that I want to communicate. I want the parent to
\be able to fprintf to the child's stdin and to fscanf from the child's
\stdout. I know that I need to fork and then in the child do an execlp,
\but I can't figure out how to set up the file descriptors so I can do
\what I want.
Other people already solved Lorien's problem, but the next is a related one.
I know why the following program doesn't work. The quiz is:
can YOU figure out why it fails? (Prizes to /dev/null.)
----------------------------------------------------------------------
#include <stdio.h>
#include <signal.h>
#define my_dup2(a, b) (dup2(a, b) != -1 || panic("Dup failed"))
char Text[] = "This is the text";
int down[2], up[2];
main()
{
char *whoami;
int catch(), chpid;
signal(SIGPIPE, catch);
if (pipe(down) != 0)
panic("error creating pipe down");
if (pipe(up) != 0)
panic("error creating pipe up");
switch (chpid = fork()) {
case -1:
panic("Fork failed");
case 0:
whoami = "Child";
do_child();
break;
default:
whoami = "Parent";
fprintf(stderr, "Child pid is %d\n", chpid);
do_parent();
break;
}
fprintf(stderr, "%s exits\n", whoami);
}
do_parent()
{
FILE *fp;
char buf[100];
int nr_read;
fprintf(stderr, "Parent pipe\n");
/* Connect write end of down to std output */
close(1);
my_dup2(down[1], 1);
close(down[1]);
/* Connect read end of up to std input */
close(0);
my_dup2(up[0], 0);
close(up[0]);
/* Convert output file descriptor to stream */
if ((fp = fdopen(1, "w")) == NULL)
panic("Can't convert descriptor to stream");
fprintf(fp, "%s", Text);
if (fclose(fp) == EOF)
panic("Fclose failed");
/* Child now sees EOF --> terminates */
fprintf(stderr, "Just before read\n");
/* Read results back from child */
while ((nr_read = read(0, buf, sizeof buf)) > 0)
fprintf(stderr, "received '%.*s'\n", nr_read, buf);
}
do_child()
{
/* Connect read end of down to std input */
close(0);
my_dup2(down[0], 0);
close(down[0]);
/* Connect write end of up to std output */
close(1);
my_dup2(up[1], 1);
close(up[1]);
/* Exec the actual child program */
fprintf(stderr, "Just before exec\n");
execl("/bin/cat", "cat", (char *) 0);
panic("Exec failed");
}
panic(msg)
char *msg;
{
fprintf(stderr, "Panic: %s\n", msg);
exit(1);
}
catch(signo)
int signo;
{
if (signo == SIGPIPE)
fprintf(stderr, "Pipe broken\n");
else
fprintf(stderr, "Signal %d\n", signo);
exit(2);
}
--
George Bush: |Maarten Litmaath @ VU Amsterdam:
Capt. Slip of the Tongue |maart at cs.vu.nl, mcvax!botter!maart
More information about the Comp.unix.wizards
mailing list