Force children to exit

This commit is contained in:
Joop Schilder 2019-01-16 17:10:20 +01:00
parent 8d1b772382
commit d40f5d940a
3 changed files with 45 additions and 28 deletions

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
/vendor/ /vendor/
/composer.lock composer.lock
/.idea/ /.idea/
/.phpstorm/ /.phpstorm/
/.vscode/ /.vscode/

View File

@ -14,6 +14,7 @@
}, },
"require": { "require": {
"ext-pcntl": "*", "ext-pcntl": "*",
"ext-sysvshm": "*" "ext-sysvshm": "*",
"ext-posix": "*"
} }
} }

View File

@ -91,7 +91,7 @@ class Asynchronous
*/ */
$instance = self::getInstance(); $instance = self::getInstance();
foreach ($instance->children as $index => $pid) { foreach ($instance->children as $index => $pid) {
$response = pcntl_waitpid($pid, $status, WNOHANG); $response = pcntl_waitpid($pid, $status, WNOHANG | WUNTRACED);
if ($response === $pid) if ($response === $pid)
unset($instance->children[$index]); unset($instance->children[$index]);
} }
@ -104,11 +104,39 @@ class Asynchronous
{ {
$instance = self::getInstance(); $instance = self::getInstance();
while (count($instance->children) > 0) { while (count($instance->children) > 0) {
pcntl_wait($status); pcntl_wait($status, WUNTRACED);
array_shift($instance->children); array_shift($instance->children);
} }
} }
/**
* Very, very inappropriate name.
*/
public static function killChildren()
{
$instance = self::getInstance();
/*
* Require the children to terminate
*/
foreach ($instance->children as $index => $pid)
if (!posix_kill($pid, SIGKILL))
posix_kill($pid, SIGTERM);
}
/**
*
*/
public static function removedShmBlock()
{
$instance = self::getInstance();
if (is_resource($instance->shm)) {
shm_remove($instance->shm);
shm_detach($instance->shm);
}
}
/** /**
* @return int * @return int
*/ */
@ -199,38 +227,26 @@ class Asynchronous
/* /*
* The shutdown handler * The shutdown handler
*/ */
$handler = function () use (&$instance) { register_shutdown_function(function () use (&$instance) {
/*
* A child process has no business here.
*/
if ($instance->isChild) if ($instance->isChild)
return; return;
/*
* Wait for all children to finish to
* ensure that all writing to the shared
* memory block is finished.
*/
self::awaitChildren(); self::awaitChildren();
self::removedShmBlock();
/* });
* Ask the kernel to mark the shared memory
* block for removal and detach from it to
* actually allow for removal.
*/
if (is_resource($instance->shm)) {
shm_remove($instance->shm);
shm_detach($instance->shm);
}
};
/* /*
* Actually register the handler as shutdown * The signal handler
* handler and signal handler for SIGINT, SIGTERM
*/ */
register_shutdown_function($handler);
foreach ([SIGINT, SIGTERM] as $SIGNAL) foreach ([SIGINT, SIGTERM] as $SIGNAL)
pcntl_signal($SIGNAL, $handler); pcntl_signal($SIGNAL, function () use (&$instance) {
if ($instance->isChild)
return;
self::killChildren();
self::awaitChildren();
self::removedShmBlock();
});
} }
} }