update page now

Voting

: eight plus one?
(Example: nine)

The Note You're Voting On

exel at example dot com
12 years ago
pipe communications may break brains off. i want to share some stuff to avoid such result.
for proper control of the communications through the "in" and "out" pipes of the opened sub-process, remember to set both of them into non-blocking mode and especially notice that fwrite may return (int)0 but it's not an error, just process might not except input at that moment. 

so, let us consider an example of decoding gz-encoded file by using funzip as sub-process: (this is not the final version, just to show important things)

<?php
            // make gz file
            $fd=fopen("/tmp/testPipe", "w");
            for($i=0;$i<100000;$i++)
                fwrite($fd, md5($i)."\n");
            fclose($fd);

            if(is_file("/tmp/testPipe.gz"))
                unlink("/tmp/testPipe.gz");
            system("gzip /tmp/testPipe");

            // open process
            $pipesDescr=array(
                0 => array("pipe", "r"),
                1 => array("pipe", "w"),
                2 => array("file", "/tmp/testPipe.log", "a"),
            );

            $process=proc_open("zcat", $pipesDescr, $pipes);
            if(!is_resource($process)) throw new Exception("popen error");

            // set both pipes non-blocking
            stream_set_blocking($pipes[0], 0);
            stream_set_blocking($pipes[1], 0);

            ////////////////////////////////////////////////////////////////////

            $text="";
            $fd=fopen("/tmp/testPipe.gz", "r");
            while(!feof($fd))
            {
                $str=fread($fd, 16384*4);
                $try=3;
                while($str)
                {
                    $len=fwrite($pipes[0], $str);
                    while($s=fread($pipes[1], 16384*4))
                        $text.=$s;

                    if(!$len)
                    {
                        // if yo remove this paused retries, process may fail
                        usleep(200000);
                        $try--;
                        if(!$try)
                            throw new Exception("fwrite error");
                    }
                    $str=substr($str, $len);
                }
                echo strlen($text)."\n";
            }
            fclose($fd);
            fclose($pipes[0]);

            // reading the rest of output stream
            stream_set_blocking($pipes[1], 1);
            while(!feof($pipes[1]))
            {
                $s=fread($pipes[1], 16384);
                $text.=$s;
            }

            echo strlen($text)." / 3 300 000\n";
?>

<< Back to user notes page

To Top