diff --git a/doxygen/doxygen.conf b/doxygen/doxygen.conf index 371218ece..c65220fb3 100644 --- a/doxygen/doxygen.conf +++ b/doxygen/doxygen.conf @@ -1565,7 +1565,7 @@ MATHJAX_FORMAT = HTML-CSS # The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example diff --git a/src/pocketmine/PocketMine.php b/src/pocketmine/PocketMine.php index ebdf6d941..42219905e 100644 --- a/src/pocketmine/PocketMine.php +++ b/src/pocketmine/PocketMine.php @@ -127,171 +127,175 @@ namespace pocketmine { return $messages; } - if(!empty($messages = check_platform_dependencies())){ - echo PHP_EOL; - $binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown"; - critical_error("Selected PHP binary ($binary) does not satisfy some requirements."); - foreach($messages as $m){ - echo " - $m" . PHP_EOL; - } - critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html."); - echo PHP_EOL; - exit(1); - } - unset($messages); - - error_reporting(-1); - - if(\Phar::running(true) !== ""){ - define('pocketmine\PATH', \Phar::running(true) . "/"); - }else{ - define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR); - } - - $opts = getopt("", ["bootstrap:"]); - if(isset($opts["bootstrap"])){ - $bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"]; - }else{ - $bootstrap = \pocketmine\PATH . 'vendor/autoload.php'; - } - define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap); - - if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){ - require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH); - if(extension_loaded('parallel')){ - \parallel\bootstrap(\pocketmine\COMPOSER_AUTOLOADER_PATH); - } - }else{ - critical_error("Composer autoloader not found at " . $bootstrap); - critical_error("Please install/update Composer dependencies or use provided builds."); - exit(1); - } - - \ErrorUtils::setErrorExceptionHandler(); - - /* - * We now use the Composer autoloader, but this autoloader is still for loading plugins. - */ - $autoloader = new \BaseClassLoader(); - $autoloader->register(false); - - set_time_limit(0); //Who set it to 30 seconds?!?! - - ini_set("allow_url_fopen", '1'); - ini_set("display_errors", '1'); - ini_set("display_startup_errors", '1'); - ini_set("default_charset", "utf-8"); - - ini_set("memory_limit", '-1'); - - define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'resources' . DIRECTORY_SEPARATOR); - - $opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]); - - define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR); - define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR); - - if(!file_exists(\pocketmine\DATA)){ - mkdir(\pocketmine\DATA, 0777, true); - } - - define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock'); - define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b")); - if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){ - //wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the - //other server wrote its PID and released exclusive lock before we get our lock - flock(\pocketmine\LOCK_FILE, LOCK_SH); - $pid = stream_get_contents(\pocketmine\LOCK_FILE); - critical_error("Another " . \pocketmine\NAME . " instance (PID $pid) is already using this folder (" . realpath(\pocketmine\DATA) . ")."); - critical_error("Please stop the other server first before running a new one."); - exit(1); - } - ftruncate(\pocketmine\LOCK_FILE, 0); - fwrite(\pocketmine\LOCK_FILE, (string) getmypid()); - fflush(\pocketmine\LOCK_FILE); - flock(\pocketmine\LOCK_FILE, LOCK_SH); //prevent acquiring an exclusive lock from another process, but allow reading - - //Logger has a dependency on timezone - Timezone::init(); - - if(isset($opts["enable-ansi"])){ - Terminal::init(true); - }elseif(isset($opts["disable-ansi"])){ - Terminal::init(false); - }else{ - Terminal::init(); - } - - $logger = new MainLogger(\pocketmine\DATA . "server.log"); - \GlobalLogger::set($logger); - - if(extension_loaded("xdebug")){ - $logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL); - } - - if(\Phar::running(true) === ""){ - $logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance."); - } - - $version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER); - define('pocketmine\VERSION', $version->getFullVersion(true)); - - $gitHash = str_repeat("00", 20); - - if(\Phar::running(true) === ""){ - if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){ - $gitHash = trim($out); - if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified - $gitHash .= "-dirty"; + function server(){ + if(!empty($messages = check_platform_dependencies())){ + echo PHP_EOL; + $binary = version_compare(PHP_VERSION, "5.4") >= 0 ? PHP_BINARY : "unknown"; + critical_error("Selected PHP binary ($binary) does not satisfy some requirements."); + foreach($messages as $m){ + echo " - $m" . PHP_EOL; } + critical_error("Please recompile PHP with the needed configuration, or refer to the installation instructions at http://pmmp.rtfd.io/en/rtfd/installation.html."); + echo PHP_EOL; + exit(1); } - }else{ - $phar = new \Phar(\Phar::running(false)); - $meta = $phar->getMetadata(); - if(isset($meta["git"])){ - $gitHash = $meta["git"]; + unset($messages); + + error_reporting(-1); + + if(\Phar::running(true) !== ""){ + define('pocketmine\PATH', \Phar::running(true) . "/"); + }else{ + define('pocketmine\PATH', dirname(__FILE__, 3) . DIRECTORY_SEPARATOR); } - } - define('pocketmine\GIT_COMMIT', $gitHash); + $opts = getopt("", ["bootstrap:"]); + if(isset($opts["bootstrap"])){ + $bootstrap = realpath($opts["bootstrap"]) ?: $opts["bootstrap"]; + }else{ + $bootstrap = \pocketmine\PATH . 'vendor/autoload.php'; + } + define('pocketmine\COMPOSER_AUTOLOADER_PATH', $bootstrap); + if(\pocketmine\COMPOSER_AUTOLOADER_PATH !== false and is_file(\pocketmine\COMPOSER_AUTOLOADER_PATH)){ + require_once(\pocketmine\COMPOSER_AUTOLOADER_PATH); + if(extension_loaded('parallel')){ + \parallel\bootstrap(\pocketmine\COMPOSER_AUTOLOADER_PATH); + } + }else{ + critical_error("Composer autoloader not found at " . $bootstrap); + critical_error("Please install/update Composer dependencies or use provided builds."); + exit(1); + } - @define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1); - @ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors + \ErrorUtils::setErrorExceptionHandler(); - $exitCode = 0; - do{ - if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){ - $installer = new SetupWizard(); - if(!$installer->run()){ - $exitCode = -1; - break; + /* + * We now use the Composer autoloader, but this autoloader is still for loading plugins. + */ + $autoloader = new \BaseClassLoader(); + $autoloader->register(false); + + set_time_limit(0); //Who set it to 30 seconds?!?! + + ini_set("allow_url_fopen", '1'); + ini_set("display_errors", '1'); + ini_set("display_startup_errors", '1'); + ini_set("default_charset", "utf-8"); + + ini_set("memory_limit", '-1'); + + define('pocketmine\RESOURCE_PATH', \pocketmine\PATH . 'resources' . DIRECTORY_SEPARATOR); + + $opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]); + + define('pocketmine\DATA', isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR); + define('pocketmine\PLUGIN_PATH', isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR); + + if(!file_exists(\pocketmine\DATA)){ + mkdir(\pocketmine\DATA, 0777, true); + } + + define('pocketmine\LOCK_FILE_PATH', \pocketmine\DATA . 'server.lock'); + define('pocketmine\LOCK_FILE', fopen(\pocketmine\LOCK_FILE_PATH, "a+b")); + if(!flock(\pocketmine\LOCK_FILE, LOCK_EX | LOCK_NB)){ + //wait for a shared lock to avoid race conditions if two servers started at the same time - this makes sure the + //other server wrote its PID and released exclusive lock before we get our lock + flock(\pocketmine\LOCK_FILE, LOCK_SH); + $pid = stream_get_contents(\pocketmine\LOCK_FILE); + critical_error("Another " . \pocketmine\NAME . " instance (PID $pid) is already using this folder (" . realpath(\pocketmine\DATA) . ")."); + critical_error("Please stop the other server first before running a new one."); + exit(1); + } + ftruncate(\pocketmine\LOCK_FILE, 0); + fwrite(\pocketmine\LOCK_FILE, (string) getmypid()); + fflush(\pocketmine\LOCK_FILE); + flock(\pocketmine\LOCK_FILE, LOCK_SH); //prevent acquiring an exclusive lock from another process, but allow reading + + //Logger has a dependency on timezone + Timezone::init(); + + if(isset($opts["enable-ansi"])){ + Terminal::init(true); + }elseif(isset($opts["disable-ansi"])){ + Terminal::init(false); + }else{ + Terminal::init(); + } + + $logger = new MainLogger(\pocketmine\DATA . "server.log"); + \GlobalLogger::set($logger); + + if(extension_loaded("xdebug")){ + $logger->warning(PHP_EOL . PHP_EOL . PHP_EOL . "\tYou are running " . \pocketmine\NAME . " with xdebug enabled. This has a major impact on performance." . PHP_EOL . PHP_EOL); + } + + if(\Phar::running(true) === ""){ + $logger->warning("Non-packaged " . \pocketmine\NAME . " installation detected. Consider using a phar in production for better performance."); + } + + $version = new VersionString(\pocketmine\BASE_VERSION, \pocketmine\IS_DEVELOPMENT_BUILD, \pocketmine\BUILD_NUMBER); + define('pocketmine\VERSION', $version->getFullVersion(true)); + + $gitHash = str_repeat("00", 20); + + if(\Phar::running(true) === ""){ + if(Process::execute("git rev-parse HEAD", $out) === 0 and $out !== false and strlen($out = trim($out)) === 40){ + $gitHash = trim($out); + if(Process::execute("git diff --quiet") === 1 or Process::execute("git diff --cached --quiet") === 1){ //Locally-modified + $gitHash .= "-dirty"; + } + } + }else{ + $phar = new \Phar(\Phar::running(false)); + $meta = $phar->getMetadata(); + if(isset($meta["git"])){ + $gitHash = $meta["git"]; } } - //TODO: move this to a Server field - define('pocketmine\START_TIME', microtime(true)); - ThreadManager::init(); - new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH); + define('pocketmine\GIT_COMMIT', $gitHash); - $logger->info("Stopping other threads"); - $killer = new ServerKiller(8); - $killer->start(PTHREADS_INHERIT_NONE); - usleep(10000); //Fixes ServerKiller not being able to start on single-core machines + @define("INT32_MASK", is_int(0xffffffff) ? 0xffffffff : -1); + @ini_set("opcache.mmap_base", bin2hex(random_bytes(8))); //Fix OPCache address errors - if(ThreadManager::getInstance()->stopAll() > 0){ - if(\pocketmine\DEBUG > 1){ - echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL; + $exitCode = 0; + do{ + if(!file_exists(\pocketmine\DATA . "server.properties") and !isset($opts["no-wizard"])){ + $installer = new SetupWizard(); + if(!$installer->run()){ + $exitCode = -1; + break; + } } - Process::kill(getmypid()); - } - }while(false); - $logger->shutdown(); - $logger->join(); + //TODO: move this to a Server field + define('pocketmine\START_TIME', microtime(true)); + ThreadManager::init(); + new Server($autoloader, $logger, \pocketmine\DATA, \pocketmine\PLUGIN_PATH); - echo Terminal::$FORMAT_RESET . PHP_EOL; + $logger->info("Stopping other threads"); - exit($exitCode); + $killer = new ServerKiller(8); + $killer->start(PTHREADS_INHERIT_NONE); + usleep(10000); //Fixes ServerKiller not being able to start on single-core machines + + if(ThreadManager::getInstance()->stopAll() > 0){ + if(\pocketmine\DEBUG > 1){ + echo "Some threads could not be stopped, performing a force-kill" . PHP_EOL . PHP_EOL; + } + Process::kill(getmypid()); + } + }while(false); + + $logger->shutdown(); + $logger->join(); + + echo Terminal::$FORMAT_RESET . PHP_EOL; + + exit($exitCode); + } + + \pocketmine\server(); } diff --git a/src/pocketmine/scheduler/AsyncTask.php b/src/pocketmine/scheduler/AsyncTask.php index d8dd45c5e..3ba47f3cb 100644 --- a/src/pocketmine/scheduler/AsyncTask.php +++ b/src/pocketmine/scheduler/AsyncTask.php @@ -33,12 +33,12 @@ use function unserialize; * * An AsyncTask does not have its own thread. It is queued into an AsyncPool and executed if there is an async worker * with no AsyncTask running. Therefore, an AsyncTask SHOULD NOT execute for more than a few seconds. For tasks that - * run for a long time or infinitely, start another {@link \pocketmine\thread\Thread} instead. + * run for a long time or infinitely, start another thread instead. * * WARNING: Any non-Threaded objects WILL BE SERIALIZED when assigned to members of AsyncTasks or other Threaded object. * If later accessed from said Threaded object, you will be operating on a COPY OF THE OBJECT, NOT THE ORIGINAL OBJECT. * If you want to store non-serializable objects to access when the task completes, store them using - * {@link AsyncTask#storeLocal}. + * {@link AsyncTask::storeLocal}. * * WARNING: As of pthreads v3.1.6, arrays are converted to Volatile objects when assigned as members of Threaded objects. * Keep this in mind when using arrays stored as members of your AsyncTask. @@ -152,8 +152,8 @@ abstract class AsyncTask extends \Threaded{ } /** - * Call this method from {@link AsyncTask#onRun} (AsyncTask execution thread) to schedule a call to - * {@link AsyncTask#onProgressUpdate} from the main thread with the given progress parameter. + * Call this method from {@link AsyncTask::onRun} (AsyncTask execution thread) to schedule a call to + * {@link AsyncTask::onProgressUpdate} from the main thread with the given progress parameter. * * @param mixed $progress A value that can be safely serialize()'ed. */ @@ -172,9 +172,9 @@ abstract class AsyncTask extends \Threaded{ } /** - * Called from the main thread after {@link AsyncTask#publishProgress} is called. - * All {@link AsyncTask#publishProgress} calls should result in {@link AsyncTask#onProgressUpdate} calls before - * {@link AsyncTask#onCompletion} is called. + * Called from the main thread after {@link AsyncTask::publishProgress} is called. + * All {@link AsyncTask::publishProgress} calls should result in {@link AsyncTask::onProgressUpdate} calls before + * {@link AsyncTask::onCompletion} is called. * * @param mixed $progress The parameter passed to {@link AsyncTask#publishProgress}. It is serialize()'ed * and then unserialize()'ed, as if it has been cloned. @@ -205,14 +205,6 @@ abstract class AsyncTask extends \Threaded{ * Objects stored in this storage can be retrieved using fetchLocal() on the same thread that this method was called * from. * - * WARNING: Use this method carefully. It might take a long time before an AsyncTask is completed. The thread this - * is called on will keep a strong reference to variables stored using method. This may result in a light memory - * leak. Usually this does not cause memory failure, but be aware that the object may be no longer usable when the - * AsyncTask completes. Since a strong reference is retained, the objects still exist, but the implementation is - * responsible for checking whether these objects are still usable. - * (E.g. a {@link \pocketmine\World} object is no longer usable because it is unloaded while the AsyncTask is - * executing, or even a plugin might be unloaded). - * * @param string $key * @param mixed $complexData the data to store */ diff --git a/src/pocketmine/scheduler/BulkCurlTask.php b/src/pocketmine/scheduler/BulkCurlTask.php index 5037e2164..c0427fa7e 100644 --- a/src/pocketmine/scheduler/BulkCurlTask.php +++ b/src/pocketmine/scheduler/BulkCurlTask.php @@ -31,9 +31,7 @@ use function unserialize; /** * Executes a consecutive list of cURL operations. * - * The result of this AsyncTask is an array of arrays (returned from {@link Utils::simpleCurl}) or InternetException objects. - * - * @package pocketmine\scheduler + * The result of this AsyncTask is an array of arrays (returned from {@link Internet::simpleCurl}) or InternetException objects. */ class BulkCurlTask extends AsyncTask{ private $operations;