Reputation: 1439
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
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