Extract MainLoggerThread unit from MainLogger

MainLogger is no longer a Thread, as per the recent changes to pocketmine/log-pthreads.
This commit is contained in:
Dylan K. Taylor 2021-02-04 16:28:49 +00:00
parent 4b9639f6c9
commit ae75d73f48
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
13 changed files with 140 additions and 79 deletions

12
composer.lock generated
View File

@ -513,17 +513,17 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pmmp/LogPthreads.git", "url": "https://github.com/pmmp/LogPthreads.git",
"reference": "273e4ba9715c7eb916c6e50e0b92ac43b7ac389e" "reference": "634af620e1cb3b4f3c7ed356cc31d778b00fd717"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/273e4ba9715c7eb916c6e50e0b92ac43b7ac389e", "url": "https://api.github.com/repos/pmmp/LogPthreads/zipball/634af620e1cb3b4f3c7ed356cc31d778b00fd717",
"reference": "273e4ba9715c7eb916c6e50e0b92ac43b7ac389e", "reference": "634af620e1cb3b4f3c7ed356cc31d778b00fd717",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-pthreads": "~3.2.0", "ext-pthreads": "~3.2.0",
"php": ">=7.2", "php": "^7.2 || ^8.0",
"pocketmine/log": "^0.2.0 || dev-master" "pocketmine/log": "^0.2.0 || dev-master"
}, },
"conflict": { "conflict": {
@ -531,7 +531,7 @@
}, },
"require-dev": { "require-dev": {
"phpstan/extension-installer": "^1.0", "phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "0.12.63", "phpstan/phpstan": "0.12.71",
"phpstan/phpstan-strict-rules": "^0.12.4" "phpstan/phpstan-strict-rules": "^0.12.4"
}, },
"type": "library", "type": "library",
@ -549,7 +549,7 @@
"issues": "https://github.com/pmmp/LogPthreads/issues", "issues": "https://github.com/pmmp/LogPthreads/issues",
"source": "https://github.com/pmmp/LogPthreads/tree/master" "source": "https://github.com/pmmp/LogPthreads/tree/master"
}, },
"time": "2021-01-06T21:23:23+00:00" "time": "2021-02-04T15:41:29+00:00"
}, },
{ {
"name": "pocketmine/math", "name": "pocketmine/math",

View File

@ -18,6 +18,7 @@ includes:
rules: rules:
- pocketmine\phpstan\rules\DisallowEnumComparisonRule - pocketmine\phpstan\rules\DisallowEnumComparisonRule
# - pocketmine\phpstan\rules\ThreadedSupportedTypesRule
parameters: parameters:
level: 8 level: 8

View File

@ -272,8 +272,7 @@ namespace pocketmine {
} }
}while(false); }while(false);
$logger->shutdown(); $logger->shutdownLogWriterThread();
$logger->join();
echo Terminal::$FORMAT_RESET . PHP_EOL; echo Terminal::$FORMAT_RESET . PHP_EOL;

View File

@ -23,6 +23,8 @@ declare(strict_types=1);
namespace pocketmine\entity; namespace pocketmine\entity;
use function min;
final class EntitySizeInfo{ final class EntitySizeInfo{
/** @var float */ /** @var float */
private $height; private $height;

View File

@ -30,6 +30,7 @@ use pocketmine\block\utils\DyeColor;
use pocketmine\data\bedrock\DyeColorIdMap; use pocketmine\data\bedrock\DyeColorIdMap;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\ListTag;
use function count;
class Banner extends ItemBlockWallOrFloor{ class Banner extends ItemBlockWallOrFloor{
public const TAG_PATTERNS = TileBanner::TAG_PATTERNS; public const TAG_PATTERNS = TileBanner::TAG_PATTERNS;

View File

@ -30,9 +30,9 @@ use pocketmine\network\mcpe\protocol\serializer\PacketSerializer;
use pocketmine\network\mcpe\protocol\types\DimensionIds; use pocketmine\network\mcpe\protocol\types\DimensionIds;
use pocketmine\network\mcpe\protocol\types\MapDecoration; use pocketmine\network\mcpe\protocol\types\MapDecoration;
use pocketmine\network\mcpe\protocol\types\MapTrackedObject; use pocketmine\network\mcpe\protocol\types\MapTrackedObject;
use function count;
#ifndef COMPILE
use pocketmine\utils\Binary; use pocketmine\utils\Binary;
#ifndef COMPILE
use function count;
#endif #endif
class ClientboundMapItemDataPacket extends DataPacket implements ClientboundPacket{ class ClientboundMapItemDataPacket extends DataPacket implements ClientboundPacket{

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\utils; namespace pocketmine\utils;
use function getmypid;
use function preg_match; use function preg_match;
trait EnumTrait{ trait EnumTrait{

View File

@ -27,11 +27,7 @@ use LogLevel;
use pocketmine\errorhandler\ErrorTypeToStringMap; use pocketmine\errorhandler\ErrorTypeToStringMap;
use pocketmine\thread\Thread; use pocketmine\thread\Thread;
use pocketmine\thread\Worker; use pocketmine\thread\Worker;
use function fclose;
use function fopen;
use function fwrite;
use function get_class; use function get_class;
use function is_resource;
use function preg_replace; use function preg_replace;
use function sprintf; use function sprintf;
use function touch; use function touch;
@ -43,14 +39,8 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
/** @var string */ /** @var string */
protected $logFile; protected $logFile;
/** @var \Threaded */
protected $logStream;
/** @var bool */
protected $shutdown = false;
/** @var bool */ /** @var bool */
protected $logDebug; protected $logDebug;
/** @var bool */
private $syncFlush = false;
/** @var string */ /** @var string */
private $format = TextFormat::AQUA . "[%s] " . TextFormat::RESET . "%s[%s/%s]: %s" . TextFormat::RESET; private $format = TextFormat::AQUA . "[%s] " . TextFormat::RESET . "%s[%s/%s]: %s" . TextFormat::RESET;
@ -61,6 +51,9 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
/** @var string */ /** @var string */
private $timezone; private $timezone;
/** @var MainLoggerThread */
private $logWriterThread;
/** /**
* @throws \RuntimeException * @throws \RuntimeException
*/ */
@ -69,13 +62,13 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
touch($logFile); touch($logFile);
$this->logFile = $logFile; $this->logFile = $logFile;
$this->logDebug = $logDebug; $this->logDebug = $logDebug;
$this->logStream = new \Threaded;
//Child threads may not inherit command line arguments, so if there's an override it needs to be recorded here //Child threads may not inherit command line arguments, so if there's an override it needs to be recorded here
$this->mainThreadHasFormattingCodes = Terminal::hasFormattingCodes(); $this->mainThreadHasFormattingCodes = Terminal::hasFormattingCodes();
$this->timezone = Timezone::get(); $this->timezone = Timezone::get();
$this->start(PTHREADS_INHERIT_NONE); $this->logWriterThread = new MainLoggerThread($this->logFile);
$this->logWriterThread->start(PTHREADS_INHERIT_NONE);
} }
/** /**
@ -218,9 +211,12 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
$this->synchronized($c); $this->synchronized($c);
} }
public function shutdown() : void{ public function shutdownLogWriterThread() : void{
$this->shutdown = true; if(\Thread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
$this->notify(); $this->logWriterThread->shutdown();
}else{
throw new \LogicException("Only the creator thread can shutdown the logger thread");
}
} }
/** /**
@ -254,54 +250,17 @@ class MainLogger extends \AttachableThreadedLogger implements \BufferedLogger{
$attachment->call($level, $message); $attachment->call($level, $message);
} }
$this->logStream[] = $time->format("Y-m-d") . " " . TextFormat::clean($message) . PHP_EOL; $this->logWriterThread->write($time->format("Y-m-d") . " " . TextFormat::clean($message) . PHP_EOL);
$this->notify();
}); });
} }
public function syncFlushBuffer() : void{ public function syncFlushBuffer() : void{
$this->syncFlush = true; $this->logWriterThread->syncFlushBuffer();
$this->synchronized(function() : void{
$this->notify(); //write immediately
while($this->syncFlush){
$this->wait(); //block until it's all been written to disk
}
});
} }
/** public function __destruct(){
* @param resource $logResource if(!$this->logWriterThread->isJoined() && \Thread::getCurrentThreadId() === $this->logWriterThread->getCreatorId()){
*/ $this->shutdownLogWriterThread();
private function writeLogStream($logResource) : void{
while($this->logStream->count() > 0){
$chunk = $this->logStream->shift();
fwrite($logResource, $chunk);
} }
$this->synchronized(function() : void{
if($this->syncFlush){
$this->syncFlush = false;
$this->notify(); //if this was due to a sync flush, tell the caller to stop waiting
}
});
}
public function run() : void{
$logResource = fopen($this->logFile, "ab");
if(!is_resource($logResource)){
throw new \RuntimeException("Couldn't open log file");
}
while(!$this->shutdown){
$this->writeLogStream($logResource);
$this->synchronized(function() : void{
$this->wait();
});
}
$this->writeLogStream($logResource);
fclose($logResource);
} }
} }

View File

@ -0,0 +1,101 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\utils;
use function fclose;
use function fopen;
use function fwrite;
use function is_resource;
final class MainLoggerThread extends \Thread{
private string $logFile;
private \Threaded $buffer;
private bool $syncFlush = false;
private bool $shutdown = false;
public function __construct(string $logFile){
$this->buffer = new \Threaded();
$this->logFile = $logFile;
}
public function write(string $line) : void{
$this->synchronized(function() use ($line) : void{
$this->buffer[] = $line;
$this->notify();
});
}
public function syncFlushBuffer() : void{
$this->syncFlush = true;
$this->synchronized(function() : void{
$this->notify(); //write immediately
while($this->syncFlush){
$this->wait(); //block until it's all been written to disk
}
});
}
public function shutdown() : void{
$this->shutdown = true;
$this->notify();
$this->join();
}
/**
* @param resource $logResource
*/
private function writeLogStream($logResource) : void{
while($this->buffer->count() > 0){
$chunk = $this->buffer->shift();
fwrite($logResource, $chunk);
}
$this->synchronized(function() : void{
if($this->syncFlush){
$this->syncFlush = false;
$this->notify(); //if this was due to a sync flush, tell the caller to stop waiting
}
});
}
public function run() : void{
$logResource = fopen($this->logFile, "ab");
if(!is_resource($logResource)){
throw new \RuntimeException("Couldn't open log file");
}
while(!$this->shutdown){
$this->writeLogStream($logResource);
$this->synchronized(function() : void{
$this->wait();
});
}
$this->writeLogStream($logResource);
fclose($logResource);
}
}

View File

@ -21,13 +21,13 @@
declare(strict_types=1); declare(strict_types=1);
if(!defined('LEVELDB_ZLIB_RAW_COMPRESSION')){ if(!\defined('LEVELDB_ZLIB_RAW_COMPRESSION')){
//leveldb might not be loaded //leveldb might not be loaded
define('LEVELDB_ZLIB_RAW_COMPRESSION', 4); \define('LEVELDB_ZLIB_RAW_COMPRESSION', 4);
} }
if(!extension_loaded('libdeflate')){ if(!\extension_loaded('libdeflate')){
function libdeflate_deflate_compress(string $data, int $level = 6) : string{} function libdeflate_deflate_compress(string $data, int $level = 6) : string{}
} }
//TODO: these need to be defined properly or removed //TODO: these need to be defined properly or removed
define('pocketmine\COMPOSER_AUTOLOADER_PATH', dirname(__DIR__, 2) . '/vendor/autoload.php'); \define('pocketmine\COMPOSER_AUTOLOADER_PATH', \dirname(__DIR__, 2) . '/vendor/autoload.php');

View File

@ -283,7 +283,7 @@ parameters:
- -
message: "#^Parameter \\#2 \\$str of function fwrite expects string, mixed given\\.$#" message: "#^Parameter \\#2 \\$str of function fwrite expects string, mixed given\\.$#"
count: 1 count: 1
path: ../../../src/utils/MainLogger.php path: ../../../src/utils/MainLoggerThread.php
- -
message: "#^Cannot access offset 'status' on mixed\\.$#" message: "#^Cannot access offset 'status' on mixed\\.$#"

View File

@ -21,14 +21,14 @@
declare(strict_types=1); declare(strict_types=1);
require dirname(__DIR__, 3) . '/vendor/autoload.php'; require \dirname(__DIR__, 3) . '/vendor/autoload.php';
/* This script needs to be re-run after any intentional blockfactory change (adding or removing a block state). */ /* This script needs to be re-run after any intentional blockfactory change (adding or removing a block state). */
$factory = new \pocketmine\block\BlockFactory(); $factory = new \pocketmine\block\BlockFactory();
$old = json_decode(file_get_contents(__DIR__ . '/block_factory_consistency_check.json'), true); $old = \json_decode(\file_get_contents(__DIR__ . '/block_factory_consistency_check.json'), true);
$new = array_map( $new = \array_map(
function(\pocketmine\block\Block $block) : string{ function(\pocketmine\block\Block $block) : string{
return $block->getName(); return $block->getName();
}, },
@ -46,6 +46,6 @@ foreach($new as $k => $name){
echo "Name changed (" . ($k >> 4) . ":" . ($k & 0xf) . "): " . $old[$k] . " -> " . $name . "\n"; echo "Name changed (" . ($k >> 4) . ":" . ($k & 0xf) . "): " . $old[$k] . " -> " . $name . "\n";
} }
} }
file_put_contents(__DIR__ . '/block_factory_consistency_check.json', json_encode( \file_put_contents(__DIR__ . '/block_factory_consistency_check.json', \json_encode(
$new $new
)); ));

View File

@ -50,8 +50,7 @@ class AsyncPoolTest extends TestCase{
public function tearDown() : void{ public function tearDown() : void{
$this->pool->shutdown(); $this->pool->shutdown();
$this->mainLogger->shutdown(); $this->mainLogger->shutdownLogWriterThread();
$this->mainLogger->join();
} }
public function testTaskLeak() : void{ public function testTaskLeak() : void{