diff --git a/src/pocketmine/CrashDump.php b/src/pocketmine/CrashDump.php index ee4be7864..8d289f370 100644 --- a/src/pocketmine/CrashDump.php +++ b/src/pocketmine/CrashDump.php @@ -130,32 +130,36 @@ class CrashDump{ } private function baseCrash(){ - global $lastError; + global $lastExceptionError, $lastError; - $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"] = cleanPath($error["file"]); - $error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"]; - if(($pos = strpos($error["message"], "\n")) !== false){ - $error["message"] = substr($error["message"], 0, $pos); + if(isset($lastExceptionError)){ + $error = $lastExceptionError; + }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"] = cleanPath($error["file"]); + $error["type"] = isset($errorConversion[$error["type"]]) ? $errorConversion[$error["type"]] : $error["type"]; + if(($pos = strpos($error["message"], "\n")) !== false){ + $error["message"] = substr($error["message"], 0, $pos); + } } if(isset($lastError)){ diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index 3294804ac..50e31768b 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -172,13 +172,16 @@ namespace pocketmine { } } - function getTrace($start = 1){ - if(function_exists("xdebug_get_function_stack")){ - $trace = array_reverse(xdebug_get_function_stack()); - }else{ - $e = new \Exception(); - $trace = $e->getTrace(); + function getTrace($start = 1, $trace = null){ + if($trace === null){ + 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){ @@ -203,7 +206,7 @@ namespace pocketmine { return rtrim(str_replace(["\\", ".php", "phar://", rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PATH), "/"), rtrim(str_replace(["\\", "phar://"], ["/", ""], \pocketmine\PLUGIN_PATH), "/")], ["/", "", "", "", ""], $path), "/"); } - function error_handler($errno, $errstr, $errfile, $errline){ + function error_handler($errno, $errstr, $errfile, $errline, $trace = null){ global $lastError; if(error_reporting() === 0){ //@ error-control return false; @@ -234,7 +237,8 @@ namespace pocketmine { $oldFile = $errfile; $errfile = cleanPath($errfile); $logger->log($type, "An $errno error happened: \"$errstr\" in \"$errfile\" at line $errline"); - foreach(($trace = getTrace(3)) as $i => $line){ + + foreach(($trace = getTrace($trace === null ? 3 : 0, $trace)) as $i => $line){ $logger->debug($line); } $lastError = [ diff --git a/src/pocketmine/Server.php b/src/pocketmine/Server.php index f4467c220..2c19835de 100644 --- a/src/pocketmine/Server.php +++ b/src/pocketmine/Server.php @@ -1053,7 +1053,7 @@ class Server{ } if(($provider = LevelProviderManager::getProviderByName($this->getProperty("level-settings.default-format", "mcregion"))) === null){ - $provider = "pocketmine\\level\\format\\mcregion\\McRegion"; + $provider = LevelProviderManager::getProviderByName("mcregion"); } $path = $this->getDataPath() . "worlds/" . $name . "/"; @@ -1450,7 +1450,7 @@ class Server{ $this->setConfigInt("difficulty", 3); } - define("pocketmine\\DEBUG", $this->getProperty("debug.level", 1)); + define("pocketmine\\DEBUG", (int) $this->getProperty("debug.level", 1)); if($this->logger instanceof MainLogger){ $this->logger->setLogDebug(\pocketmine\DEBUG > 1); } @@ -1490,8 +1490,9 @@ class Server{ $this->pluginManager->setUseTimings($this->getProperty("settings.enable-profiling", false)); $this->pluginManager->registerInterface("pocketmine\\plugin\\PharPluginLoader"); - register_shutdown_function(array($this, "crashDump")); - register_shutdown_function(array($this, "forceShutdown")); + set_exception_handler([$this, "exceptionHandler"]); + register_shutdown_function([$this, "crashDump"]); + register_shutdown_function([$this, "forceShutdown"]); $this->pluginManager->loadPlugins($this->pluginPath); @@ -1805,6 +1806,20 @@ class Server{ } } + public function exceptionHandler(\Exception $e){ + if($e === null){ + return; + } + + error_handler(E_ERROR, $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTrace()); + global $lastExceptionError, $lastError; + $lastExceptionError = $lastError; + $this->crashDump(); + $this->forceShutdown(); + kill(getmypid()); + exit(1); + } + public function crashDump(){ if($this->isRunning === false){ return;