paarandika
paarandika

Reputation: 1439

C pipe not functioning with large writes

Wrote a little script to work with php5-cgi using fork(),exec() and pipes. Script below works well when output of php5-cgi is small. But when it's considerably large (when using <?php phpinfo(); ?> in the input file), it does not return anything.

#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<fcntl.h>

int main(int argc, char const *argv[]) {

  int status;
  int link[2];
  char out[4096];
  char * arg[3]={"php5-cgi","a.php",0};
  if (pipe(link)==-1){
    perror("pipe");
  }
  int pid=fork();
  if (!pid){
    dup2 (link[1], 1);
    close(link[0]);
    execvp("php5-cgi", arg);
  } else {
    waitpid(pid, &status,0);
    close(link[1]); // parent doesn't write
        char reading_buf[1];
        while(read(link[0], reading_buf, 1) > 0){
            write(1, reading_buf, 1);
        }
        close(link[0]);
  }
  printf("%s\n", "end");
  return 0;
}

I assume this is due to overflow of pipe. I there any way to fix this issue? Or is there any alternatives to deal with large ouput?

Upvotes: 3

Views: 1882

Answers (1)

Nate Eldredge
Nate Eldredge

Reputation: 58132

The pipe buffer is relatively small, usually a few Kbytes. The child can write to it until the buffer is full; then further writes will block until some of the data has been read.

Your parent calls waitpid before attempting to read from the pipe. So it is waiting for the child to terminate. But if the child is blocked trying to write, it will never terminate. So you never get past the waitpid in this case.

What you probably want to do is move the waitpid after the read/write loop. Then the child can continue writing more data as you read it. When the read() finally fails, it is likely because the child has exited and closed its end of the pipe. So you can do waitpid at that time to get the exit status and reap the zombie.

Also, check the return values of all your system calls! And compile with warnings turned on (this will alert you that you forgot to #include <sys/wait.h>).

Upvotes: 6

Related Questions