I am building on a SunFire T2000, Solaris 10 os. The test programs replaces the stdin and stdout fds of the child with pipes from the parent. I keep thinking there has to be a stupid mistake here somewhere but I can't find it and everyone I show it to thinks it should work too.
I ran test using 2, 3, 8 and 12 with success, the parent could either write to child or read from child. Tests using 10, 11, 14, 15 all failed, whenever the parent tried either writing then reading or writing then waiting neither the child or parent completed and I had to <CTR>C to end it. Compile options: gcc -c -O -DSYSV -DSVR4 -Wa,-cg92 -I.. -D SUN -DUSEPROTO -Wall -ffloat-store -DSOLARIS main.c gcc -o runtest -O -DSYS -DSVR4 -Wa,-cg92 main.o -lm -lposix4 -lgen -lsocket -lnsl -Wl,-R,/usr/lib gcc -c -O -DSYSV -DSVR4 -Wa,-cg92 -I.. -D SUN -DUSEPROTO -Wall -ffloat-store -DSOLARIS child.c gcc -o childtest -O -DSYS -DSVR4 -Wa,-cg92 child.o -lm -lposix4 -lgen -lsocket -lnsl -Wl,-R,/usr/lib main.c #include <ctype.h> #include <unistd.h> #include <sys/types> #include <sys/stat.h> #include <sys/socket.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> #define PIPE_READ 0 #define PIPE_WRITE 1 int main (int argc, char *argv[]) { int infds[2], outfds[2], pid, tempfd, testpath; FILE *childIn, *childOut; char childData[80]; char *parentData; parentData = "This is the parent data.\n"; if (0 > pipe(infds)) { exit(1); } fprintf(stderr, "infds = [%d, %d]\n", infds[PIPE_READ], infds[PIPE_WRITE]); if (0 > pipe(outfds)) { exit(1); } fprintf(stderr, "outfds = [%d, %d]\n", outfds[PIPE_READ], outfds[PIPE_WRITE]); pid = fork(); fprintf(stderr, "pid = %d\n", pid); fflush(stderr); switch (pid) { case -1: perror("Fork failed"); exit(1); case 0: /* child */ close(0); /* setup standard in */ tempfd = dup(infds[PIPE_READ]); if (tempfd < 0) { perror("Setup stdin dup failed"); exit(1); } fprintf(stderr, "Child new stdin fd = %d\n", tempfd); while ((0 != close(infds[PIPE_READ])) && (EINTR == errno)); while ((0 != close(infds[PIPE_WRITE])) && (EINTR == errno)); close(1); /* setup standard out */ tempfd = dup(outfds[PIPE_WRITE]); if (tempfd < 0) { perror("Setup stdout dup failed"); exit(1); } fprintf(stderr, "Child new stdout fd = %d\n", tempfd); while ((0 != close(outfds[PIPE_READ])) && (EINTR == errno)); while ((0 != close(outfds[PIPE_WRITE])) && (EINTR == errno)); if (1 < argc) { execl("./childtest", "./childtest", argv[argc - 1], (char *)0); } else { execl("./childtest", "./childtest", (char *)0); } perror("Exec child failed"); exit(1); default: break; } while ((0 != close(infds[PIPE_READ]) && (EINTR == errno)); childIn = fopen(infds[PIPE_WRITE], "w"); if (NULL == childIn) { perror("Parent creating child's stdin FILE"); } while ((0 != close(outfds[PIPE_WRITE]) && (EINTR == errno)); childOut = fopen(outfds[PIPE_READ], "r"); if (NULL == childOut) { perror("Parent creating child's stdout FILE"); } if (1 < argc) { testpath = atoi(argv[argc - 1]); } else { testpath = 15; } if (testpath & 1) { sleep(1); } if (testpath & 2) { fprintf(stderr, "Parent sends: %s", parentData); fflush(stderr); fputs(parentData, childIn); } if (testpath & 4) { int status; fputs("Parent waiting\n", stderr); while (wait(&status) != pid) { fputs("Parent woke but not child\n", stderr); } fprintf(stderr, "Parent woke, child status: %d\n", status); } if (testpath & 8) { fputs("Parent reading child's stdout\n", stderr); fflush(stderr); if (NULL == fgets(childData, 80, childOut)) { fprintf(stderr, "Parent receive: NOTHING\n"); } else { fprintf(stderr, "Parent receive: %s\n", childData); } fflush(stderr); } fclose(childIn); fclose(childOut); fputs("Parent completed\n", stderr); fflush(stderr); exit(0); } child.c #include <ctype.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> int main (int argc, char *argv[]) { int testpath; char recvData[180]; char *sendData; sendData = "This is the child data.\n"; fputs("Starting child\n", stderr); fflush(stderr); if (argc > 1) { testpath = atoi(argv[argc - 1]); } else { testpath = 15; } if (testpath & 2) { fputs("Child reading\n", stderr); fflush(stderr); if (NULL == fgets(recvData, 160, stdin)) { fputs("child receive NULL\n", stderr); fflush(stderr); exit(1); } fprintf(stderr, "child received: %s\n", recvData); fflush(stderr); } if (testpath & 8) { fputs("Child sleeping\n", stderr); sleep(1); /* Simulat child processing */ fprintf(stderr, "Child sending: %s\n", sendData); fflush(stderr); fputs(sendData, stdout); } fputs("Child completed\n"); fflush(stderr); return(0); } I had to type this all in by hand so I am hoping there is no typos -- Summary: Replacing both stdin and stdout on forked child does not work. Product: gcc Version: 3.4.6 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: alvin dot j dot rearick at saic dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30776