fopen function is blocked in php
===

I am writing php script running on the linux called by crontab. As there are many network accessing in the process, so it' better to use multi-process to decrease the whole running time.So I choose the pcntol_fork and posix_mkfifo. To Simplize the process, my script is following:

    <?php
    define('PROC_NUM', 5);
    define('PIPE_PRE', 'my_pipe_');
    define('MAX_BUFFER', 30);
    define('TIME_COST_DELAY', 5); // max delay
    define('SELECT_WAIT', 1); // stream_select timeout
    define('READ_BUFFER', 10); // reading buffer size

    ////////////////////////////////////////////////////////////////////////////
    /////////////////////////////////////main///////////////////////////////////
    declare(ticks=1);
    pcntl_signal(SIGCHLD, 'SignalChild');

    $arrPipe = array();
    $arrChild = array();
    for ($i = 0; $i < PROC_NUM; ++$i) {
        // create pipe for sync
        $sPipePath = PIPE_PRE . $i;
        if (!posix_mkfifo($sPipePath, 0666)) {
            die("failed to make pipe {$sPipePath}");
        }
        $arrPipe[] = $sPipePath;
        
        $nPID = pcntl_fork();
        if ($nPID < 0) {
            die('fork failed');
        } else if ($nPID == 0) {
            // child process
            ChildProcess($sPipePath);
            exit(0);
        } else {
            $arrChild[] = $nPID;
        }
    }

    echo "parent 1\n";

    // parent open all pipe
    $arrRd = array();
    $arrDecoder = array();
    foreach($arrPipe as $sPipePath) {
        echo "parent 1.1\n";
        $oRd = fopen($sPipePath, 'r');
        echo "parent 1.2\n";
        if ($oRd == FALSE) {
            die("open pipe {$sPipePath} for reading error");
        }
        stream_set_blocking($oRd, FALSE);
        $arrRd[] = $oRd;
        
        $arrDecoder[] = new Decoder();
    }
    echo "parent 2\n";

    $arrRst = array();
    while (count($arrRd)) {
        $read = $arrRd;
        echo "parent 2.1\n";
        if (FALSE === stream_select($read, $w = NULL, $e = NULL, SELECT_WAIT)) {
            continue;
        }
        foreach($read as $oRd) {
            $nID = array_search($oRd, $arrRd);
            if(!$arrDecoder[$nID]->Decode($oRd)) {
                $arrRst[] = $arrDecoder[$nID]->GetContent();

                fclose($arrRd[$nID]);
                unset($arrRd[$nID]);
                unset($arrDecoder[$nID]);
            }
        }
    }

    // clear all pipe
    foreach($arrPipe as $sPipePath) {
        unlink($sPipePath);
    }

    var_dump($arrRst); // show the result
    /////////////////////////////////////main///////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////
    class Decoder {
        private $nSize;
        private $sCnt;
        
        public function __construct() {
            $this->nSize = -1; 
            $sCnt = 0;
        }

        /*
         * @param $oRd pipe reader
         * @return true for continue，false for break
         */
        public function Decode($oRd) {
            if ($this->nSize < 0) {
                $arrSize = unpack('N', fread($oRd, 4));
                $this->nSize = $arrSize[1];
            }
          
            while(!feof($oRd)) {
                $this->sCnt .= fread($oRd, READ_BUFFER);
            }
            
            return !$this->IsFinished();
        }
        
        public function IsFinished() {
            return strlen($this->sCnt) >= $this->nSize; 
        }
        
        public function GetContent() {return $this->sCnt;}
        
    }

    /*
     * child process 
     */
    function ChildProcess($sPipePath) {
        sleep(rand(1, TIME_COST_DELAY)); // simulate network time cost
        
        $nData = rand(1, MAX_BUFFER); // simulate data length
        echo "Child generate data (size {$nData}) to pipe({$sPipePath})\n";
        
        $oWr = fopen($sPipePath, 'w');
        if ($oWr == FALSE) {
            echo "Child failed to open pipe {$sPipePath}\n";
            return ;
        }
        if (!fwrite($oWr, pack('N', $nData))) {
            echo "Child write size error\n";
            fclose($oWr);
            return ;
        }
        if (!fwrite($oWr, str_repeat('a', $nData))) {
            echo "Child write content error\n";
            fclose($oWr);
            return ;
        }
        fclose($oWr);
    }

    function SignalChild($nSignal) {
        global $arrChild;
        pcntl_signal(SIGCHLD, 'SignalChild');
        
        $nStatus = -1;
        $nPID = -1;
        echo "Catch Signal\n";
        while (($nPID = pcntl_wait($nStatus, WNOHANG)) > 0) {
            $arrChild = array_diff($arrChild, array($nPID));
            echo "Catch Child {$nPID}\n";
        }
    }

    ?>

So the result of the script is following:

    parent 1
    parent 1.1
    Child generate data (size 6) to pipe(my_pipe_2)
    Child generate data (size 6) to pipe(my_pipe_0)
    Child generate data (size 10) to pipe(my_pipe_4)
    Child generate data (size 14) to pipe(my_pipe_1)
    Child generate data (size 25) to pipe(my_pipe_3)
It seems that the parent process blocked by the php build-in funciton fopen. If commenting the first 2 lines of the main rountine, that is registering the signal handling function, the above condition will be avoided, and the termiante will show the data genenated by the child process, so I doubt that the signal event cause the problem, isn't?  
So, how to solve this problem.

My environment:
Linux 2.6.16.60-0.21-xenpae-100302-time i686 i686 i386 GNU/Linux
php v5.2.14
