CommandReader: removed readline support

readline has been borked for a long time and it's not thread safe.
This commit is contained in:
Dylan K. Taylor
2021-01-25 17:53:25 +00:00
parent 31b6df4376
commit 62deafda48

View File

@ -25,23 +25,18 @@ namespace pocketmine\command;
use pocketmine\snooze\SleeperNotifier; use pocketmine\snooze\SleeperNotifier;
use pocketmine\Thread; use pocketmine\Thread;
use pocketmine\utils\Utils;
use function extension_loaded;
use function fclose; use function fclose;
use function fgets; use function fgets;
use function fopen; use function fopen;
use function fstat; use function fstat;
use function getopt;
use function is_resource; use function is_resource;
use function microtime; use function microtime;
use function preg_replace; use function preg_replace;
use function readline; use function readline;
use function readline_add_history;
use function stream_isatty; use function stream_isatty;
use function stream_select; use function stream_select;
use function trim; use function trim;
use function usleep; use function usleep;
use const STDIN;
class CommandReader extends Thread{ class CommandReader extends Thread{
@ -65,12 +60,6 @@ class CommandReader extends Thread{
public function __construct(?SleeperNotifier $notifier = null){ public function __construct(?SleeperNotifier $notifier = null){
$this->buffer = new \Threaded; $this->buffer = new \Threaded;
$this->notifier = $notifier; $this->notifier = $notifier;
$opts = getopt("", ["disable-readline", "enable-readline"]);
if(extension_loaded("readline") and (Utils::getOS() === Utils::OS_WINDOWS ? isset($opts["enable-readline"]) : !isset($opts["disable-readline"])) and !$this->isPipe(STDIN)){
$this->type = self::TYPE_READLINE;
}
} }
/** /**
@ -128,41 +117,34 @@ class CommandReader extends Thread{
*/ */
private function readLine() : bool{ private function readLine() : bool{
$line = ""; $line = "";
if($this->type === self::TYPE_READLINE){
if(($raw = readline("> ")) !== false and ($line = trim($raw)) !== ""){
readline_add_history($line);
}else{
return true;
}
}else{
if(!is_resource(self::$stdin)){
$this->initStdin();
}
switch($this->type){ if(!is_resource(self::$stdin)){
/** @noinspection PhpMissingBreakStatementInspection */ $this->initStdin();
case self::TYPE_STREAM: }
//stream_select doesn't work on piped streams for some reason
$r = [self::$stdin];
$w = $e = null;
if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
return true;
}elseif($count === false){ //stream error
$this->initStdin();
}
case self::TYPE_PIPED: switch($this->type){
if(($raw = fgets(self::$stdin)) === false){ //broken pipe or EOF /** @noinspection PhpMissingBreakStatementInspection */
$this->initStdin(); case self::TYPE_STREAM:
$this->synchronized(function() : void{ //stream_select doesn't work on piped streams for some reason
$this->wait(200000); $r = [self::$stdin];
}); //prevent CPU waste if it's end of pipe $w = $e = null;
return true; //loop back round if(($count = stream_select($r, $w, $e, 0, 200000)) === 0){ //nothing changed in 200000 microseconds
} return true;
}elseif($count === false){ //stream error
$this->initStdin();
}
$line = trim($raw); case self::TYPE_PIPED:
break; if(($raw = fgets(self::$stdin)) === false){ //broken pipe or EOF
} $this->initStdin();
$this->synchronized(function() : void{
$this->wait(200000);
}); //prevent CPU waste if it's end of pipe
return true; //loop back round
}
$line = trim($raw);
break;
} }
if($line !== ""){ if($line !== ""){
@ -193,17 +175,11 @@ class CommandReader extends Thread{
*/ */
public function run(){ public function run(){
$this->registerClassLoader(); $this->registerClassLoader();
$this->initStdin();
if($this->type !== self::TYPE_READLINE){
$this->initStdin();
}
while(!$this->shutdown and $this->readLine()); while(!$this->shutdown and $this->readLine());
if($this->type !== self::TYPE_READLINE){ fclose(self::$stdin);
fclose(self::$stdin);
}
} }
public function getThreadName() : string{ public function getThreadName() : string{