Path: utzoo!utgpu!attcan!uunet!mcvax!hp4nl!botter!star.cs.vu.nl!maart From: maart@cs.vu.nl (Maarten Litmaath) Newsgroups: comp.unix.wizards Subject: deadlock quiz (was: How to do a pipe & fork?) Message-ID: <1626@solo8.cs.vu.nl> Date: 5 Nov 88 01:35:18 GMT References: <4629@mtgzz.att.com> <4630@mtgzz.att.com> Reply-To: maart@cs.vu.nl (Maarten Litmaath) Organization: VU Informatica, Amsterdam Lines: 131 \In article , pratt@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 #include #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@cs.vu.nl, mcvax!botter!maart