Distinguish between direct and indirect plugin crash involvement

If a plugin was involved in a crash, we can't safely blame it for the crash, since it might have innocently triggered a core bug. Furthermore, it's difficult to accurately detect plugin causing things like invalid argument crashes.
This commit is contained in:
Dylan K. Taylor 2018-12-27 17:18:46 +00:00
parent 2cdf97b7b5
commit 22a6b817d7

View File

@ -87,7 +87,11 @@ class CrashDump{
* having their content changed, version format changing, etc. * having their content changed, version format changing, etc.
* It is not necessary to increase this when adding new fields. * It is not necessary to increase this when adding new fields.
*/ */
private const FORMAT_VERSION = 1; private const FORMAT_VERSION = 2;
private const PLUGIN_INVOLVEMENT_NONE = "none";
private const PLUGIN_INVOLVEMENT_DIRECT = "direct";
private const PLUGIN_INVOLVEMENT_INDIRECT = "indirect";
/** @var Server */ /** @var Server */
private $server; private $server;
@ -245,13 +249,13 @@ class CrashDump{
$this->addLine("Line: " . $error["line"]); $this->addLine("Line: " . $error["line"]);
$this->addLine("Type: " . $error["type"]); $this->addLine("Type: " . $error["type"]);
$this->data["plugin"] = false; $this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_NONE;
if(!$this->determinePluginFromFile($error["fullFile"])){ //fatal errors won't leave any stack trace if(!$this->determinePluginFromFile($error["fullFile"], true)){ //fatal errors won't leave any stack trace
foreach($error["trace"] as $frame){ foreach($error["trace"] as $frame){
if(!isset($frame["file"])){ if(!isset($frame["file"])){
continue; //PHP core continue; //PHP core
} }
if($this->determinePluginFromFile($frame["file"])){ if($this->determinePluginFromFile($frame["file"], false)){
break; break;
} }
} }
@ -277,12 +281,17 @@ class CrashDump{
$this->addLine(); $this->addLine();
} }
private function determinePluginFromFile(string $filePath) : bool{ private function determinePluginFromFile(string $filePath, bool $crashFrame) : bool{
$frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub $frameCleanPath = Utils::cleanPath($filePath); //this will be empty in phar stub
if($frameCleanPath !== "" and strpos($frameCleanPath, "src/pocketmine/") === false and strpos($frameCleanPath, "vendor/pocketmine/") === false and file_exists($filePath)){ if($frameCleanPath !== "" and strpos($frameCleanPath, "src/pocketmine/") === false and strpos($frameCleanPath, "vendor/pocketmine/") === false and file_exists($filePath)){
$this->addLine(); $this->addLine();
if($crashFrame){
$this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN"); $this->addLine("THIS CRASH WAS CAUSED BY A PLUGIN");
$this->data["plugin"] = true; $this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_DIRECT;
}else{
$this->addLine("A PLUGIN WAS INVOLVED IN THIS CRASH");
$this->data["plugin_involvement"] = self::PLUGIN_INVOLVEMENT_INDIRECT;
}
$reflection = new \ReflectionClass(PluginBase::class); $reflection = new \ReflectionClass(PluginBase::class);
$file = $reflection->getProperty("file"); $file = $reflection->getProperty("file");