mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-08-11 05:52:05 +00:00
RakLibServer: fixed deadlock on thread crash
synchronized block -> getCrashInfo -> join -> synchronized on the same context on the child thread -> deadlock instead we check for isTerminated and then get the crash info outside of the synchronized block.
This commit is contained in:
parent
a83c62a4a2
commit
89d18f929f
@ -68,17 +68,17 @@ class RakLibServer extends Thread{
|
|||||||
public function startAndWait(int $options = NativeThread::INHERIT_NONE) : void{
|
public function startAndWait(int $options = NativeThread::INHERIT_NONE) : void{
|
||||||
$this->start($options);
|
$this->start($options);
|
||||||
$this->synchronized(function() : void{
|
$this->synchronized(function() : void{
|
||||||
while(!$this->ready && $this->getCrashInfo() === null){
|
while(!$this->ready && !$this->isTerminated()){
|
||||||
$this->wait();
|
$this->wait();
|
||||||
}
|
}
|
||||||
$crashInfo = $this->getCrashInfo();
|
|
||||||
if($crashInfo !== null){
|
|
||||||
if($crashInfo->getType() === SocketException::class){
|
|
||||||
throw new SocketException($crashInfo->getMessage());
|
|
||||||
}
|
|
||||||
throw new ThreadCrashException("RakLib failed to start", $crashInfo);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
$crashInfo = $this->getCrashInfo();
|
||||||
|
if($crashInfo !== null){
|
||||||
|
if($crashInfo->getType() === SocketException::class){
|
||||||
|
throw new SocketException($crashInfo->getMessage());
|
||||||
|
}
|
||||||
|
throw new ThreadCrashException("RakLib failed to start", $crashInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function onRun() : void{
|
protected function onRun() : void{
|
||||||
|
@ -100,6 +100,8 @@ trait CommonThreadPartsTrait{
|
|||||||
//*before* the shutdown handler is invoked, so we might land here before the crash info has been set.
|
//*before* the shutdown handler is invoked, so we might land here before the crash info has been set.
|
||||||
//In the future this should probably be fixed by running the shutdown handlers before setting isTerminated,
|
//In the future this should probably be fixed by running the shutdown handlers before setting isTerminated,
|
||||||
//but this workaround should be good enough for now.
|
//but this workaround should be good enough for now.
|
||||||
|
//WARNING: Do not call this inside a synchronized block on this thread's context. Because the shutdown handler
|
||||||
|
//runs in a synchronized block, this will result in a deadlock.
|
||||||
if($this->isTerminated() && !$this->isJoined()){
|
if($this->isTerminated() && !$this->isJoined()){
|
||||||
$this->join();
|
$this->join();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user