Fixed getTrace() on crash with xdebug

This commit is contained in:
Shoghi Cervantes 2014-07-27 17:31:39 +02:00
parent f53d513894
commit 6d77b0883e
3 changed files with 63 additions and 29 deletions

View File

@ -119,29 +119,40 @@ class CrashDump{
} }
private function baseCrash(){ private function baseCrash(){
$error = (array) error_get_last(); global $lastError;
$errorConversion = array( if(isset($lastError)){
E_ERROR => "E_ERROR", $error = $lastError;
E_WARNING => "E_WARNING", }else{
E_PARSE => "E_PARSE", $error = (array) error_get_last();
E_NOTICE => "E_NOTICE", $error["trace"] = getTrace(4);
E_CORE_ERROR => "E_CORE_ERROR", $errorConversion = array(
E_CORE_WARNING => "E_CORE_WARNING", E_ERROR => "E_ERROR",
E_COMPILE_ERROR => "E_COMPILE_ERROR", E_WARNING => "E_WARNING",
E_COMPILE_WARNING => "E_COMPILE_WARNING", E_PARSE => "E_PARSE",
E_USER_ERROR => "E_USER_ERROR", E_NOTICE => "E_NOTICE",
E_USER_WARNING => "E_USER_WARNING", E_CORE_ERROR => "E_CORE_ERROR",
E_USER_NOTICE => "E_USER_NOTICE", E_CORE_WARNING => "E_CORE_WARNING",
E_STRICT => "E_STRICT", E_COMPILE_ERROR => "E_COMPILE_ERROR",
E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR", E_COMPILE_WARNING => "E_COMPILE_WARNING",
E_DEPRECATED => "E_DEPRECATED", E_USER_ERROR => "E_USER_ERROR",
E_USER_DEPRECATED => "E_USER_DEPRECATED", E_USER_WARNING => "E_USER_WARNING",
); E_USER_NOTICE => "E_USER_NOTICE",
$fullFile = $error["file"]; E_STRICT => "E_STRICT",
$error["file"] = str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $error["file"]); E_RECOVERABLE_ERROR => "E_RECOVERABLE_ERROR",
$error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"]; 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; $this->data["error"] = $error;
unset($this->data["error"]["fullFile"]);
unset($this->data["error"]["trace"]);
$this->addLine("Error: ". $error["message"]); $this->addLine("Error: ". $error["message"]);
$this->addLine("File: ". $error["file"]); $this->addLine("File: ". $error["file"]);
$this->addLine("Line: ". $error["line"]); $this->addLine("Line: ". $error["line"]);
@ -158,14 +169,14 @@ class CrashDump{
$this->addLine(); $this->addLine();
$this->addLine("Code:"); $this->addLine("Code:");
$this->data["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){ for($l = max(0, $error["line"] - 10); $l < $error["line"] + 10; ++$l){
$this->addLine("[" . ($l + 1) . "] " . @$file[$l]); $this->addLine("[" . ($l + 1) . "] " . @$file[$l]);
$this->data["code"][$l + 1] = @$file[$l]; $this->data["code"][$l + 1] = @$file[$l];
} }
$this->addLine(); $this->addLine();
$this->addLine("Backtrace:"); $this->addLine("Backtrace:");
foreach(($this->data["trace"] = getTrace(3)) as $line){ foreach(($this->data["trace"] = $error["trace"]) as $line){
$this->addLine($line); $this->addLine($line);
} }
$this->addLine(); $this->addLine();

View File

@ -173,24 +173,34 @@ namespace pocketmine {
} }
function getTrace($start = 1){ function getTrace($start = 1){
$e = new \Exception(); if(function_exists("xdebug_get_function_stack")){
$trace = $e->getTrace(); $trace = array_reverse(xdebug_get_function_stack());
}else{
$e = new \Exception();
$trace = $e->getTrace();
}
$messages = []; $messages = [];
$j = 0; $j = 0;
for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){ for($i = (int) $start; isset($trace[$i]); ++$i, ++$j){
$params = ""; $params = "";
if(isset($trace[$i]["args"])){ if(isset($trace[$i]["args"]) or isset($trace[$i]["params"])){
foreach($trace[$i]["args"] as $name => $value){ 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)) . ", "; $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; return $messages;
} }
function error_handler($errno, $errstr, $errfile, $errline){ function error_handler($errno, $errstr, $errfile, $errline){
global $lastError;
if(error_reporting() === 0){ //@ error-control if(error_reporting() === 0){ //@ error-control
return false; 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; $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; $errno = isset($errorConversion[$errno]) ? $errorConversion[$errno] : $errno;
if(($pos = strrpos($errstr, "\n")) !== false){
$errstr = substr($errstr, 0, $pos);
}
$logger = MainLogger::getLogger(); $logger = MainLogger::getLogger();
$oldFile = $errfile;
$errfile = str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $errfile); $errfile = str_replace(["\\", ".php", str_replace("\\", "/", \pocketmine\PATH)], ["/", "", ""], $errfile);
$logger->log($type, "An $errno error happened: \"$errstr\" in \"$errfile\" at line $errline"); $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); $logger->debug($line);
} }
$lastError = [
"type" => $type,
"message" => $errstr,
"fullFile" => $oldFile,
"file" => $errfile,
"line" => $errline,
"trace" => $trace
];
return true; return true;
} }

View File

@ -1780,6 +1780,7 @@ class Server{
} }
public function crashDump(){ public function crashDump(){
if($this->isRunning === false){ if($this->isRunning === false){
return; return;
} }