diff --git a/src/pocketmine/CrashDump.php b/src/pocketmine/CrashDump.php index 38e00e7d7b..c7e140bd30 100644 --- a/src/pocketmine/CrashDump.php +++ b/src/pocketmine/CrashDump.php @@ -119,29 +119,40 @@ class CrashDump{ } private function baseCrash(){ - $error = (array) error_get_last(); - $errorConversion = array( - E_ERROR => "E_ERROR", - E_WARNING => "E_WARNING", - E_PARSE => "E_PARSE", - E_NOTICE => "E_NOTICE", - E_CORE_ERROR => "E_CORE_ERROR", - E_CORE_WARNING => "E_CORE_WARNING", - E_COMPILE_ERROR => "E_COMPILE_ERROR", - E_COMPILE_WARNING => "E_COMPILE_WARNING", - E_USER_ERROR => "E_USER_ERROR", - E_USER_WARNING => "E_USER_WARNING", - E_USER_NOTICE => "E_USER_NOTICE", - E_STRICT => "E_STRICT", - E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR", - E_DEPRECATED => "E_DEPRECATED", - E_USER_DEPRECATED => "E_USER_DEPRECATED", - ); - $fullFile = $error["file"]; - $error["file"] = str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $error["file"]); - $error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"]; + global $lastError; + if(isset($lastError)){ + $error = $lastError; + }else{ + $error = (array) error_get_last(); + $error["trace"] = getTrace(4); + $errorConversion = array( + E_ERROR => "E_ERROR", + E_WARNING => "E_WARNING", + E_PARSE => "E_PARSE", + E_NOTICE => "E_NOTICE", + E_CORE_ERROR => "E_CORE_ERROR", + E_CORE_WARNING => "E_CORE_WARNING", + E_COMPILE_ERROR => "E_COMPILE_ERROR", + E_COMPILE_WARNING => "E_COMPILE_WARNING", + E_USER_ERROR => "E_USER_ERROR", + E_USER_WARNING => "E_USER_WARNING", + E_USER_NOTICE => "E_USER_NOTICE", + E_STRICT => "E_STRICT", + E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR", + E_DEPRECATED => "E_DEPRECATED", + E_USER_DEPRECATED => "E_USER_DEPRECATED", + ); + $error["fullFile"] = $error["file"]; + $error["file"] = str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $error["file"]); + $error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"]; + if(($pos = strrpos($error["message"], "\n")) !== false){ + $error["message"] = substr($error["message"], 0, $pos); + } + } $this->data["error"] = $error; + unset($this->data["error"]["fullFile"]); + unset($this->data["error"]["trace"]); $this->addLine("Error: ". $error["message"]); $this->addLine("File: ". $error["file"]); $this->addLine("Line: ". $error["line"]); @@ -158,14 +169,14 @@ class CrashDump{ $this->addLine(); $this->addLine("Code:"); $this->data["code"] = []; - $file = @file($fullFile, FILE_IGNORE_NEW_LINES); + $file = @file($error["fullFile"], FILE_IGNORE_NEW_LINES); for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10; ++$l){ $this->addLine("[" . ($l + 1) . "] " . @$file[$l]); $this->data["code"][$l + 1] = @$file[$l]; } $this->addLine(); $this->addLine("Backtrace:"); - foreach(($this->data["trace"] = getTrace(3)) as $line){ + foreach(($this->data["trace"] = $error["trace"]) as $line){ $this->addLine($line); } $this->addLine(); diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index 7d5d6daa78..95b43f37b9 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -173,24 +173,34 @@ namespace pocketmine { } function getTrace($start = 1){ - $e = new \Exception(); - $trace = $e->getTrace(); + if(function_exists("xdebug_get_function_stack")){ + $trace = array_reverse(xdebug_get_function_stack()); + }else{ + $e = new \Exception(); + $trace = $e->getTrace(); + } $messages = []; $j = 0; for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){ $params = ""; - if(isset($trace[$i]["args"])){ - foreach($trace[$i]["args"] as $name => $value){ + if(isset($trace[$i]["args"]) or isset($trace[$i]["params"])){ + if(isset($trace[$i]["args"])){ + $args = $trace[$i]["args"]; + }else{ + $args = $trace[$i]["params"]; + } + foreach($args as $name => $value){ $params .= (is_object($value) ? get_class($value) . " " . (method_exists($value, "__toString") ? $value->__toString() : "object") : gettype($value) . " " . @strval($value)) . ", "; } } - $messages[] = "#$j " . (isset($trace[$i]["file"]) ? str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . $trace[$i]["type"] : "") . $trace[$i]["function"] . "(" . substr($params, 0, -2) . ")"; + $messages[] = "#$j " . (isset($trace[$i]["file"]) ? str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $trace[$i]["file"]) : "") . "(" . (isset($trace[$i]["line"]) ? $trace[$i]["line"] : "") . "): " . (isset($trace[$i]["class"]) ? $trace[$i]["class"] . (($trace[$i]["type"] === "dynamic" or $trace[$i]["type"] === "->") ? "->" : "::") : "") . $trace[$i]["function"] . "(" . substr($params, 0, -2) . ")"; } return $messages; } function error_handler($errno, $errstr, $errfile, $errline){ + global $lastError; if(error_reporting() === 0){ //@ error-control return false; } @@ -213,12 +223,24 @@ namespace pocketmine { ); $type = ($errno === E_ERROR or $errno === E_WARNING or $errno === E_USER_ERROR or $errno === E_USER_WARNING) ? LogLevel::ERROR : LogLevel::NOTICE; $errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno; + if(($pos = strrpos($errstr, "\n")) !== false){ + $errstr = substr($errstr, 0, $pos); + } $logger = MainLogger::getLogger(); + $oldFile = $errfile; $errfile = str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $errfile); $logger->log($type, "An $errno error happened: \"$errstr\" in \"$errfile\" at line $errline"); - foreach(getTrace() as $i => $line){ + foreach(($trace = getTrace(3)) as $i => $line){ $logger->debug($line); } + $lastError = [ + "type" => $type, + "message" => $errstr, + "fullFile" => $oldFile, + "file" => $errfile, + "line" => $errline, + "trace" => $trace + ]; return true; } diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index 242e657ae8..3c86232c88 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -1780,6 +1780,7 @@ class Server{ } public function crashDump(){ + if($this->isRunning === false){ return; }