Skip to content

Commit

Permalink
BUGFIX fix race-condition which sometimes blocks the proper script-exit
Browse files Browse the repository at this point in the history
  • Loading branch information
sweikenb committed Aug 3, 2024
1 parent 6521239 commit 1e15637
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 11 deletions.
8 changes: 5 additions & 3 deletions src/PoolManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ public function __construct(?ProcessManagerInterface $processManager = null,)
// create the process manager instance if not provided
$this->pm = $processManager ?? new ProcessManager();

// register/override interrupt handler for the main-process
// register/override interrupt- and termination-handler for the main-process
pcntl_signal(SIGINT, [$this, 'handleInterrupt']);
pcntl_signal(SIGTERM, [$this, 'handleInterrupt']);

// register events
$this->pm->onThreadCreate(function (ChildProcessInterface $process) {
Expand All @@ -34,7 +35,7 @@ public function handleInterrupt(): void
$this->pm->sendSignalToChildren(SIGTERM);
}

public function execute(int $poolSize, callable $mainLoop, callable $processLoop, ?float $killTimeout = null): int
public function execute(int $poolSize, callable $mainLoop, callable $processLoop, ?float $killTimeout = null): never
{
while (!$this->interrupted) {
// ensure we have enough threads
Expand Down Expand Up @@ -65,6 +66,7 @@ public function execute(int $poolSize, callable $mainLoop, callable $processLoop
// final wait until all children exited after the KILL
$this->pm->wait();

return $status;
// terminate the script with the proper exit-code
exit($status);
}
}
2 changes: 1 addition & 1 deletion src/ProcessManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public function wait(?callable $callback = null, bool $block = true): void

// wait for all children to exit
$wait = true;
while ($wait && !empty($this->childProcesses)) {
while ($wait && (!empty($this->childProcesses) || !empty($this->childExitQueue))) {
// process the exit-queue
foreach ($this->childExitQueue as $pid => $status) {
if ($pid > 0) {
Expand Down
66 changes: 59 additions & 7 deletions tests/ProcessManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ function (ChildProcessInterface $process, ParentProcessInterface $parentProcess)
$parentProcess->sendMessage(
$factory->create(sprintf('answer from #%d', $i), 'hello')
);

return $message !== null
&& $message->getTopic() === sprintf("hello my child %d", $i)
&& $message->getPayload() === 'hello';
Expand All @@ -161,29 +162,80 @@ function (ChildProcessInterface $process, ParentProcessInterface $parentProcess)
/**
* @covers \Sweikenb\Library\Pcntl\ProcessManager::wait
*/
public function testWait(): void
public function testWaitBlock(): void
{
$pm = new ProcessManager();

$numChilds = 100;
for ($i = 1; $i <= $numChilds; $i++) {
$pm->runProcess(function () use ($i) {
usleep($i * 10);
return true;
});
}

$numClosed = 0;
$numWaitLoops = 0;
while ($numChilds > $numClosed) {
$numWaitLoops++;
$pm->wait(function () use (&$numClosed) {
$numClosed++;
return $numClosed > 50;
++$numClosed;
});
}

$this->assertSame($numChilds, $numClosed);
}

/**
* @covers \Sweikenb\Library\Pcntl\ProcessManager::wait
*/
public function testWaitUnblock(): void
{
$pm = new ProcessManager();

$numChilds = 100;
for ($i = 1; $i <= $numChilds; $i++) {
$pm->runProcess(function () {
sleep(1);
});
}

$this->assertSame(51, $numWaitLoops);
$numClosed = 0;
$pm->wait(
function () use (&$numClosed) {
++$numClosed;
},
false
);
$pm->wait();

$this->assertSame(0, $numClosed);
}

/**
* @covers \Sweikenb\Library\Pcntl\ProcessManager::wait
*/
public function testWaitInlineUnblock(): void
{
$pm = new ProcessManager();

$numChilds = 100;
for ($i = 1; $i <= $numChilds; $i++) {
$pm->runProcess(function () {
usleep(10);
});
}
sleep(1);

$numClosed = 0;
$pm->wait(
function () use (&$numClosed) {
++$numClosed;

return false;
}
);
$pm->wait();

$this->assertGreaterThan(0, $numClosed);
$this->assertLessThan($numChilds, $numClosed);
}

/**
Expand Down

0 comments on commit 1e15637

Please sign in to comment.