1
0
mirror of https://github.com/danog/parallel.git synced 2024-11-27 04:44:56 +01:00

Fix killing a thread; avoid issues with signals

This commit is contained in:
Aaron Piotrowski 2015-09-05 12:52:56 -05:00
parent 3f097bab4c
commit b163207cea
3 changed files with 35 additions and 12 deletions

View File

@ -158,14 +158,9 @@ class Fork implements ContextInterface
case 0: // Child case 0: // Child
// @codeCoverageIgnoreStart // @codeCoverageIgnoreStart
// We will have a cloned event loop from the parent after forking. The // Create a new event loop in the fork.
// child context by default is synchronous and uses the parent event $loop = Loop\create(false);
// loop, so we need to stop the clone before doing any work in case it Loop\loop($loop);
// is already running.
$loop = Loop\loop();
$loop->stop();
$loop->reInit();
$loop->clear();
$channel = new Channel(new DuplexStream($parent)); $channel = new Channel(new DuplexStream($parent));
fclose($child); fclose($child);

View File

@ -17,6 +17,8 @@ use Icicle\Socket\Stream\DuplexStream;
*/ */
class Thread extends \Thread class Thread extends \Thread
{ {
const KILL_CHECK_FREQUENCY = 0.25;
/** /**
* @var callable The function to execute in the thread. * @var callable The function to execute in the thread.
*/ */
@ -32,6 +34,11 @@ class Thread extends \Thread
*/ */
private $socket; private $socket;
/**
* @var bool
*/
private $killed = false;
/** /**
* Creates a new thread object. * Creates a new thread object.
* *
@ -67,13 +74,32 @@ class Thread extends \Thread
} }
} }
$loop = Loop\create(false); // Disable signals in thread.
Loop\loop($loop);
// At this point, the thread environment has been prepared so begin using the thread. // At this point, the thread environment has been prepared so begin using the thread.
$channel = new Channel(new DuplexStream($this->socket)); $channel = new Channel(new DuplexStream($this->socket));
$coroutine = new Coroutine($this->execute($channel)); $coroutine = new Coroutine($this->execute($channel));
$coroutine->done(); $coroutine->done();
Loop\run(); $timer = $loop->timer(self::KILL_CHECK_FREQUENCY, true, function () use ($loop, $coroutine, $channel) {
if ($this->killed) {
$loop->stop();
}
});
$timer->unreference();
$loop->run();
}
/**
* Sets a local variable to true so the running event loop can check for a kill signal.
*/
public function kill()
{
$this->killed = true;
parent::kill();
} }
/** /**

View File

@ -138,11 +138,13 @@ class Thread implements ContextInterface
*/ */
public function kill() public function kill()
{ {
if (null === $this->thread) {
throw new StatusError('The thread has not been started.');
}
$this->close(); $this->close();
if ($this->isRunning() && !$this->thread->kill()) { $this->thread->kill();
throw new ThreadException('Failed to kill the thread.');
}
} }
/** /**