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

Reply via email to