How to solve the problem of php stream_socket_pair random entry?

originally uses stream_socket_pair to communicate between parent and child processes. In multiple processes, one child process message is forwarded to other child processes through the parent process (similar to qq ), but this encounters a problem:

$count     = 4;
$childConn = [];
$parent    = null;

for ($i = 0; $i < $count; PP$i)
{
    $pair = stream_socket_pair(STREAM_PF_UNIX , STREAM_SOCK_STREAM , STREAM_IPRROTO_IP);
    $pid = pcntl_fork();
    
    if ($pid < 0) {
        throw new Exception("");
    } else if ($pid > 0) {
        fclose($pair[1]);
        $child = $pair[0];
        $childConn[$pid] = $child;
        // 
        listenChild($child); 
    } else {
        fclose($pair[0]);
        $parent = $pair[1];
        // 
        listenParent($parent);
    }
}
The purpose of

above is to create a communication channel with the parent process for each child process, but the result is unexpected!

for example, the following communication process:

pid: 30246
pid: 30247 30248 30249 30250

1. A  30247
2. B  30248
3. A  30247  30248  B
4.  30247  $parent
... 
30246

stream_socket_pair 

I am speechless. Get down on your knees and beg the great god for rescue

Feb.28,2021

< H1 > the code of deceiving people is restored as follows < / H1 >
use Event\Event;
use Event\Select;

$pid_list = [];
$parent_pid = posix_getpid();

for ($i = 0; $i < 4; PP$i)
{
    $pair = stream_socket_pair(STREAM_PF_UNIX , STREAM_SOCK_STREAM , STREAM_IPPROTO_IP);
    
    $pid = pcntl_fork();
    
    if ($pid < 0) {
        throw new Exception("");
    } else if ($pid > 0) {
        // 
        fclose($pair[0]);
        
        $child = $pair[1];
        
        fwrite($child , " " . posix_getpid());
        
        Select::addIo($child , Event::READ , function($ctrl , $socket , $child) use($parent_pid){
            $msg = fread($socket , 65535);
            
            echo " {$parent_pid}  " . posix_getpid() . " :{$msg}" . PHP_EOL;
        } , $child);
    } else {
        // 
        fclose($pair[1]);
        $parent = $pair[0];
        fwrite($parent , " " . posix_getpid());
        
        Select::addIo($parent , Event::READ , function($ctrl , $socket , $parent) use($parent_pid){
            $msg = fread($socket , 65535);
            
            echo " " . posix_getpid() . "  " . posix_getpid() . " :{$msg}\n";
        } , $parent);
    }
}

generated process information:

:32140
:32141 32142 32143 32144

result of deceiving people:

under the parent process code domain (the child process intrudes into the parent process domain! )

 32140  32142   32141
 32140  32143   32142
 32140  32144   32143
 32140  32140   32144

Child process code domain (correct)

 32141  32141   32140
 32142  32142   32140
 32143  32143   32140
 32144  32144   32140

Analysis: why does the child process call the event defined in the parent process?

this requires a careful analysis of the for loop!

  • the first loop, the parent process adds a child process listening event to Event::$events , and the child process executes in parallel. For the first child process generated, Event::$events is empty, so there are no events copied to the parent process.
  • In the
  • second loop, the parent process adds a listening child process event to Event::$events again, and there is an event Event::$events for the resulting second child process! An event was copied from the parent process.
  • In the
  • third loop, the parent process once again adds listening child process events to Event::$events . At this time, for the three generated child processes, Event::$events has two events! Two events are copied from the parent process.
  • In the
  • fourth loop, the parent process again adds events to the Event::$evnets . At this time, there are three events in Event::$events relative to the fourth child process that is generated, and three events are copied from the parent process.

from the above, we know that the child process is actually listening for events copied from the parent process, and if the event is triggered, the parent-child process that listens for the event will actually trigger it. As a result, there is something depressing: the child process intrudes into the realm of the parent process.

< H1 > solution < / H1 >

in the child process, destroy the events copied from the parent process.

for ($i = 0; $i < 4; PP$i)
{
    $pid = pcntl_fork();
    
    if ($pid < 0) {
        throw new Exception("");
    } else if ($pid > 0) {
        // 
        Select::addIo( .... );
        // ...
    } else {
        // 
        // 
        Select::clear();
        
        // ....
    }
}
Menu