diff --git a/library/CM/Process.php b/library/CM/Process.php index acc1b673b..b0a864ca7 100644 --- a/library/CM/Process.php +++ b/library/CM/Process.php @@ -2,6 +2,7 @@ class CM_Process { + const FORKING_DELAY = 200; const RESPAWN_TIMEOUT = 10; /** @var Closure|null */ @@ -165,6 +166,7 @@ private function _fork(Closure $workload, $sequence) { throw new CM_Exception('Cannot open stream socket pair'); } $pid = pcntl_fork(); + usleep(self::FORKING_DELAY); if ($pid === -1) { throw new CM_Exception('Could not spawn child process'); } diff --git a/tests/library/CM/ProcessTest.php b/tests/library/CM/ProcessTest.php index b883a768e..54adba9bc 100644 --- a/tests/library/CM/ProcessTest.php +++ b/tests/library/CM/ProcessTest.php @@ -36,38 +36,43 @@ public function testFork() { */ public function testForkAndWaitForChildren() { $process = CM_Process::getInstance(); + $parentOutput = []; for ($i = 1; $i <= 4; $i++) { - CM_ProcessTest::writeln("Child $i forked."); + $parentOutput[] = "Child $i forked."; $process->fork(function () use ($i) { $ms = 100 * $i; usleep($ms * 1000); CM_ProcessTest::writeln("Child $i terminated after $ms ms."); }); } - CM_ProcessTest::writeln('Parent waiting for 250 ms...'); + $parentOutput[] = 'Parent waiting for 250 ms...'; usleep(250000); - CM_ProcessTest::writeln('Parent listening to children...'); - $process->waitForChildren(null, function () { - CM_ProcessTest::writeln('All children terminated.'); + $parentOutput[] = 'Parent listening to children...'; + $process->waitForChildren(null, function () use (&$parentOutput) { + $parentOutput[] = 'All children terminated.'; }); - CM_ProcessTest::writeln('Parent terminated.'); + $parentOutput[] = 'Parent terminated.'; - $outputFileExpected = 'Child 1 forked. -Child 2 forked. -Child 3 forked. -Child 4 forked. -Parent waiting for 250 ms... -Child 1 terminated after 100 ms. -Child 2 terminated after 200 ms. -Parent listening to children... -Child 3 terminated after 300 ms. -Child 4 terminated after 400 ms. -All children terminated. -Parent terminated. -'; rewind(self::$_file); - $outputFileActual = fread(self::$_file, 8192); - $this->assertEquals($outputFileExpected, $outputFileActual); + $childrenOutput = explode("\n", fread(self::$_file, 8192)); + + $this->assertSame([ + 'Child 1 forked.', + 'Child 2 forked.', + 'Child 3 forked.', + 'Child 4 forked.', + 'Parent waiting for 250 ms...', + 'Parent listening to children...', + 'All children terminated.', + 'Parent terminated.' + ], $parentOutput); + + $this->assertContainsAll([ + 'Child 2 terminated after 200 ms.', + 'Child 1 terminated after 100 ms.', + 'Child 3 terminated after 300 ms.', + 'Child 4 terminated after 400 ms.', + ], $childrenOutput); } /**