[comp.sys.sgi] Problem with pipe/fork

gaumondp@JSP.UMontreal.CA (Gaumond Pierre) (04/16/91)

The following program creates a pipe and generates two processes with fork. The
parent reads data from standard input and writes it to the pipe. The child
reads the pipe and writes data to the standard output.

Quite simple. However, it doesn't work.

The program reads all the data and everything is transfered (I have tried a
small file as a redirection of input). The processes block after the last
character is transfered to the standard output. The processes seem to wait for
something... for what? EOF?

I understood that the "fclose" on the write end of the pipe would generate an
EOF status at the read end. Is it correct. Perhaps the problem is somewhere
else...

-------------------------------------------------------------------------------
<necessary include files>

main()
{
  FILE *fp;
  int fdi[2];
  char c;
  
  pipe(fdi);
  if (fork()!=0)
  { /* parent */
    fp=fdopen(fdi[1],"w");
    for (c=getchar(); !feof(stdin); c=getchar()) fputc(c,fp);
    fclose(fp);
    wait(0);
  }
  else
  { /* child */
    fp=fdopen(fdi[0],"r");
    for (c=fgetc(fp); !feof(fp); c=fgetc(fp)) putchar(c);
    fclose(fp);
  }
}

-------------------------------------------------------------------------------

Pierre Gaumond.
-- 
Pierre Gaumond.                                 | gaumondp@JSP.UMontreal.CA
Services Informatiques, Universite de Montreal. | gaumondp@centrcn.UMontreal.CA
C.P. 6128, Succursale "A", Montreal,            |
Quebec, Canada.   H3C 3J7                       |

pj@sam.wpd.sgi.com (Paul Jackson) (04/17/91)

In article <1991Apr16.150557.2344@jsp.umontreal.ca>, gaumondp@JSP.UMontreal.CA (Gaumond
Pierre) writes:
[[ Sample program presented that has parent writing pipe to child.
   He asks why child doesn't notice EOF on the pipe after the parent closes it. ]]

|>   int fdi[2];
|>   
|>   pipe(fdi);
|>   if (fork()!=0) { /* parent */
	[[ Loops writing to fdi[1], then closes fdi[1]. ]]
|>   } else { /* child */
	[[ Loops reading from fdi[0] until eof - but eof never seen. ]]
|>   }
|> }

In the child, before the loop until eof, add the line:

	close(fdi[1]);

The fork resulted in both the parent and child having
fdi[1] open for writing, and the child will see eof
on fdi[0] only when all available writers to the pipe
have closed the write end.

-- 

				I won't rest till it's the best ...
				Software Production Engineer
				Paul Jackson (pj@wpd.sgi.com), x1373

corbettm@cutmcvax.cutmcvax.cs.curtin.edu.au (Michael Corbett) (04/17/91)

gaumondp@JSP.UMontreal.CA (Gaumond Pierre) writes:

>The following program creates a pipe and generates two processes with fork. The
>parent reads data from standard input and writes it to the pipe. The child
>reads the pipe and writes data to the standard output.

>Quite simple. However, it doesn't work.

>The program reads all the data and everything is transfered (I have tried a
>small file as a redirection of input). The processes block after the last
>character is transfered to the standard output. The processes seem to wait for
>something... for what? EOF?

>I understood that the "fclose" on the write end of the pipe would generate an
>EOF status at the read end. Is it correct. Perhaps the problem is somewhere
>else...

This is partially correct... The EOF is not sent to the pipe until all the
file descriptors have have closed in every process... due to the fork there
are 2 file descriptors (one in each process) associated with the write end
of the pipe.... So these both need to be closed before the loop in the 
child process

For neatness you should also close the read end of the pipe in the 
parent process...

I have added the appropriate lines in the code below... (Hope it helps)

>-------------------------------------------------------------------------------
><necessary include files>

>main()
>{
>  FILE *fp;
>  int fdi[2];
>  char c;
>  
>  pipe(fdi);
>  if (fork()!=0)
>  { /* parent */
     close (fdi[0]);
>    fp=fdopen(fdi[1],"w");
>    for (c=getchar(); !feof(stdin); c=getchar()) fputc(c,fp);
>    fclose(fp);
>    wait(0);
>  }
>  else
>  { /* child */
     close (fdi[1]);
>    fp=fdopen(fdi[0],"r");
>    for (c=fgetc(fp); !feof(fp); c=fgetc(fp)) putchar(c);
>    fclose(fp);
>  }
>}

--

>>           Michael Corbett             | "Last night, I thought my arm was <<
>> corbettm@anger.cipal.cs.curtin.edu.au | hanging out of bed.  So I got out <<
>> corbettm@cutmcvax.cs.curtin.edu.au    | to push it in."                   <<