pmmp / PocketMine-MP

A server software for Minecraft: Bedrock Edition in PHP
https://pmmp.io
GNU Lesser General Public License v3.0
3.26k stars 1.54k forks source link

PluginLoadTriageEntry could not be converted to string #4518

Closed RoyalMCPE closed 2 years ago

RoyalMCPE commented 2 years ago

Link to crashdump: https://pastebin.com/cA8gkLfe

Additional comments (optional)

This seems to only occur when running under wsl2, and setting the --plugins opt to a directory outside of the vm. Example: /mnt/c/dev/plugins/

DaisukeDaisuke commented 2 years ago

This crashdump is generated by 4.0.0-BETA7(Probably built from source code.). This bug existed before 4.0.0-BETA6, and has been fixed in 4.0.0-BETA7 release.

parameters

/PocketMine-MP.phar --plugins /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins/

error and backtrace

Object of class pocketmine\\plugin\\PluginLoadTriageEntry could not be converted to string
pmsrc/src/plugin/PluginManager.php on line 358
#0 pmsrc/src/plugin/PluginManager(358): array_diff_assoc(array[6], array[1])
#1 pmsrc/src/Server(973): pocketmine\\plugin\\PluginManager->loadPlugins(string[61] /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins/)
#2 pmsrc/src/PocketMine(293): pocketmine\\Server->__construct(object BaseClassLoader#3, object pocketmine\\utils\\MainLogger#2, string[23] /home/royalmcpe/Server/, string[62] /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins//)
#3 pmsrc/src/PocketMine(316): pocketmine\\server()
#4 pmsrc(11): require(string[67] phar:///home/royalmcpe/Server/PocketMine-MP.phar/src/PocketMine.php)

codes

Line 358. https://github.com/pmmp/PocketMine-MP/blob/0ef5c67b9b6b2b42b42e9e93001299b784dd96b9/src/plugin/PluginManager.php#L358 https://github.com/pmmp/PocketMine-MP/blob/0ef5c67b9b6b2b42b42e9e93001299b784dd96b9/src/plugin/PluginManager.php#L354-L360

OS and versions

Plugins

array (
  'format_version' => 4,
  'time' => 1635388657.742997,
  'uptime' => 0.3912179470062256,
  'lastError' =>
  array (
    'type' => 'Error',
    'message' => 'Object of class pocketmine\\plugin\\PluginLoadTriageEntry could not be converted to string',
    'fullFile' => 'phar:///home/royalmcpe/Server/PocketMine-MP.phar/src/plugin/PluginManager.php',
    'file' => 'pmsrc/src/plugin/PluginManager',
    'line' => 358,
    'trace' =>
    array (
      0 => '#0 pmsrc/src/plugin/PluginManager(358): array_diff_assoc(array[6], array[1])',
      1 => '#1 pmsrc/src/Server(973): pocketmine\\plugin\\PluginManager->loadPlugins(string[61] /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins/)',
      2 => '#2 pmsrc/src/PocketMine(293): pocketmine\\Server->__construct(object BaseClassLoader#3, object pocketmine\\utils\\MainLogger#2, string[23] /home/royalmcpe/Server/, string[62] /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins//)',
      3 => '#3 pmsrc/src/PocketMine(316): pocketmine\\server()',
      4 => '#4 pmsrc(11): require(string[67] phar:///home/royalmcpe/Server/PocketMine-MP.phar/src/PocketMine.php)',
    ),
  ),
  'error' =>
  array (
    'type' => 'Error',
    'message' => 'Object of class pocketmine\\plugin\\PluginLoadTriageEntry could not be converted to string',
    'file' => 'pmsrc/src/plugin/PluginManager',
    'line' => 358,
  ),
  'plugin_involvement' => 'none',
  'code' =>
  array (
    349 => '                                            foreach($this->fileAssociations as $k => $loader){',
    350 => '                                                    if(!array_key_exists($k, $oldRegisteredLoaders)){',
    351 => '                                                            $diffLoaders[] = $k;',
    352 => '                                                    }',
    353 => '                                            }',
    354 => '                                            if(count($diffLoaders) !== 0){',
    355 => '                                                    $this->server->getLogger()->debug("Plugin $name registered a new plugin loader during load, scanning for new plugins");',
    356 => '                                                    $plugins = $triage->plugins;',
    357 => '                                                    $this->triagePlugins($path, $triage, $diffLoaders);',
    358 => '                                                    $diffPlugins = array_diff_assoc($triage->plugins, $plugins);',
    359 => '                                                    $this->server->getLogger()->debug("Re-triage found plugins: " . implode(", ", array_keys($diffPlugins)));',
    360 => '                                            }',
    361 => '                                    }',
    362 => '                            }',
    363 => '                    }',
    364 => '',
    365 => '                    if($loadedThisLoop === 0){',
    366 => '                            //No plugins loaded :(',
    367 => '',
    368 => '                            //check for skippable soft dependencies first, in case the dependents could resolve hard dependencies',
  ),
  'trace' =>
  array (
    0 => '#0 pmsrc/src/plugin/PluginManager(358): array_diff_assoc(array[6], array[1])',
    1 => '#1 pmsrc/src/Server(973): pocketmine\\plugin\\PluginManager->loadPlugins(string[61] /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins/)',
    2 => '#2 pmsrc/src/PocketMine(293): pocketmine\\Server->__construct(object BaseClassLoader#3, object pocketmine\\utils\\MainLogger#2, string[23] /home/royalmcpe/Server/, string[62] /mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins//)',
    3 => '#3 pmsrc/src/PocketMine(316): pocketmine\\server()',
    4 => '#4 pmsrc(11): require(string[67] phar:///home/royalmcpe/Server/PocketMine-MP.phar/src/PocketMine.php)',
  ),
  'general' =>
  array (
    'name' => 'PocketMine-MP',
    'base_version' => '4.0.0-BETA7',
    'build' => 0,
    'is_dev' => true,
    'protocol' => 471,
    'git' => '0ef5c67b9b6b2b42b42e9e93001299b784dd96b9-dirty',
    'uname' => 'Linux DESKTOP-UEDUS9L 5.10.16.3-microsoft-standard-WSL2 #1 SMP Sun Oct 24 22:47:46 MDT 2021 x86_64',
    'php' => '8.0.11',
    'zend' => '4.0.11',
    'php_os' => 'Linux',
    'os' => 'linux',
    'composer_libraries' =>
    array (
      'adhocore/json-comment' => '1.1.2@fc2f76979f0a44a5f5bc2a2b600d0762fe0e78e7',
      'brick/math' => '0.9.3@ca57d18f028f84f777b2168cd1911b0dee2343ae',
      'daverandom/callback-validator' => 'unknown@unknown',
      'fgrosse/phpasn1' => 'v2.3.0@20299033c35f4300eb656e7e8e88cf52d1d6694e',
      'netresearch/jsonmapper' => 'v4.0.0@8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d',
      'pocketmine/bedrock-protocol' => 'dev-master@58c53a259e819a076bf8fe875d2a012da7d19d65',
      'pocketmine/binaryutils' => '0.2.2@f883e1cf9099ed6a757a10a2f75b3333eeb2cdf9',
      'pocketmine/callback-validator' => '1.0.3@64787469766bcaa7e5885242e85c23c25e8c55a2',
      'pocketmine/classloader' => 'dev-master@80226e0917be79ac3230606113e25134a31e6a85',
      'pocketmine/color' => '0.2.0@09be6ea6d76f2e33d6813c39d29c22c46c17e1d2',
      'pocketmine/errorhandler' => '0.3.0@ec742b209e8056bbe855069c4eff94c9734ea19b',
      'pocketmine/log' => '0.3.0@03ab1316da0b1978a7a1c8dd73e1c2a973cb62ec',
      'pocketmine/log-pthreads' => '0.2.0@6be3445c48c62eba3922f987f000bb20c81d161f',
      'pocketmine/math' => '0.3.0@83ec067b12c066fc61d9fb129daf7e61ef3b1d63',
      'pocketmine/nbt' => '0.3.0@98c4a04b55a915e18f83d3b0c9beb24a71abcd31',
      'pocketmine/pocketmine-mp' => 'dev-master@0ef5c67b9b6b2b42b42e9e93001299b784dd96b9',
      'pocketmine/raklib' => '0.14.2@e3a861187470e1facc6625040128f447ebbcbaec',
      'pocketmine/raklib-ipc' => '0.1.1@922a6444b0c6c7daaa5aa5a832107e1ec4738aed',
      'pocketmine/snooze' => '0.3.0@fe5b1dbf0d6267da882d1f67924772bd93db833d',
      'pocketmine/spl' => 'dev-master@b7a8904f912c1f6d38ad867ff1120614ccb80171',
      'ramsey/collection' => '1.2.2@cccc74ee5e328031b15640b51056ee8d3bb66c0a',
      'ramsey/uuid' => '4.2.3@fc9bb7fb5388691fd7373cd44dcb4d63bbcf24df',
      'rhumsaa/uuid' => 'unknown@unknown',
      'symfony/polyfill-ctype' => 'v1.23.0@46cd95797e9df938fdd2b03693b5fca5e64b01ce',
      'symfony/polyfill-php80' => 'v1.23.1@1100343ed1a92e3a38f9ae122fc0eb21602547be',
      'symfony/polyfill-php81' => 'v1.23.0@e66119f3de95efc359483f810c4c3e6436279436',
      'webmozart/assert' => '1.10.0@6964c76c7804814a842473e0c8fd15bab0f18e25',
      'webmozart/path-util' => '2.3.0@d939f7edc24c9a1bb9c0dee5cb05d8e859490725',
    ),
  ),
  'plugins' =>
  array (
    'DevTools' =>
    array (
      'name' => 'DevTools',
      'version' => '1.15.0+dev',
      'authors' =>
      array (
        0 => 'PocketMine Team',
      ),
      'api' =>
      array (
        0 => '4.0.0',
      ),
      'enabled' => false,
      'depends' =>
      array (
      ),
      'softDepends' =>
      array (
      ),
      'main' => 'DevTools\\DevTools',
      'load' => 'STARTUP',
      'website' => 'https://github.com/PocketMine/DevTools',
    ),
  ),
  'parameters' =>
  array (
    0 => './PocketMine-MP.phar',
    1 => '--plugins',
    2 => '/mnt/c/Users/RoyalMCPE/Desktop/Server-Files/PMMPTest/plugins/',
  ),
  'server.properties' => '#Properties Config file
#Wed Oct 27 20:06:30 MDT 2021
language=eng
motd=PocketMine-MP Server
server-name=PocketMine-MP Server
server-port=19132
gamemode=0
max-players=20
white-list=on
enable-query=on
force-gamemode=off
hardcore=off
pvp=on
difficulty=2
generator-settings=
level-name=world
level-seed=
level-type=DEFAULT
auto-save=on
view-distance=8
xbox-auth=on
',
  'pocketmine.yml' => '# Main configuration file for PocketMine-MP
# These settings are the ones that cannot be included in server.properties
# Some of these settings are safe, others can break your server if modified incorrectly
# New settings/defaults won\'t appear automatically in this file when upgrading.

settings:
  #Whether to send all strings translated to server locale or let the device handle them
  force-language: false
  shutdown-message: "Server closed"
  #Allow listing plugins via Query
  query-plugins: true
  #Enable plugin and core profiling by default
  enable-profiling: false
  #Will only add results when tick measurement is below or equal to given value (default 20)
  profile-report-trigger: 20
  #Number of AsyncTask workers.
  #Used for plugin asynchronous tasks, world generation, compression and web communication.
  #Set this approximately to your number of cores.
  #If set to auto, it\'ll try to detect the number of cores (or use 2)
  async-workers: auto
  #Whether to allow running development builds. Dev builds might crash, break your plugins, corrupt your world and more.
  #It is recommended to avoid using development builds where possible.
  enable-dev-builds: true

memory:
  #Global soft memory limit in megabytes. Set to 0 to disable
  #This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this
  global-limit: 0

  #Main thread soft memory limit in megabytes. Set to 0 to disable
  #This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this
  main-limit: 0

  #Main thread hard memory limit in megabytes. Set to 0 to disable
  #This will stop the server when the limit is surpassed
  main-hard-limit: 1024

  #AsyncWorker threads\' hard memory limit in megabytes. Set to 0 to disable
  #This will crash the task currently executing on the worker if the task exceeds the limit
  #NOTE: THIS LIMIT APPLIES PER WORKER, NOT TO THE WHOLE PROCESS.
  async-worker-hard-limit: 256

  #Period in ticks to check memory (default 1 second)
  check-rate: 20

  #Continue firing low-memory-triggers and event while on low memory
  continuous-trigger: true

  #Only if memory.continuous-trigger is enabled. Specifies the rate in memory.check-rate steps (default 30 seconds)
  continuous-trigger-rate: 30

  garbage-collection:
    #Period in ticks to fire the garbage collector manually (default 30 minutes), set to 0 to disable
    #This only affects the main thread. Other threads should fire their own collections
    period: 36000

    #Fire asynchronous tasks to collect garbage from workers
    collect-async-worker: true

    #Trigger on low memory
    low-memory-trigger: true

  #Settings controlling memory dump handling.
  memory-dump:
    #Dump memory from async workers as well as the main thread. If you have issues with segfaults when dumping memory, disable this setting.
    dump-async-worker: true

  max-chunks:
    #Cap maximum render distance per player when low memory is triggered. Set to 0 to disable cap.
    chunk-radius: 4

    #Do chunk garbage collection on trigger
    trigger-chunk-collect: true

  world-caches:
    #Disallow adding to world chunk-packet caches when memory is low
    disable-chunk-cache: true
    #Clear world caches when memory is low
    low-memory-trigger: true

network:
  #Threshold for batching packets, in bytes. Only these packets will be compressed
  #Set to 0 to compress everything, -1 to disable.
  batch-threshold: 256
  #Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
  compression-level: 6
  #Use AsyncTasks for compression. Adds half/one tick delay, less CPU load on main thread
  async-compression: false
  #Experimental. Use UPnP to automatically port forward
  upnp-forwarding: false
  #Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be
  #fragmented or split into smaller parts. Clients can request MTU sizes up to but not more than this number.
  max-mtu-size: 1492
  #Enable encryption of Minecraft network traffic. This has an impact on performance, but prevents hackers from stealing sessions and pretending to be other players.
  #DO NOT DISABLE THIS unless you understand the risks involved.
  enable-encryption: true

debug:
  #If > 1, it will show debug messages in the console
  level: 2

player:
  #Choose whether to enable player data saving.
  save-player-data: true
  #If true, checks that joining players\' Xbox user ID (XUID) match what was previously recorded.
  #This also prevents non-XBL players using XBL players\' usernames to steal their data on servers with xbox-auth=off.
  verify-xuid: true

level-settings:
  #The default format that levels will use when created
  default-format: leveldb

chunk-sending:
  #To change server normal render distance, change view-distance in server.properties.
  #Amount of chunks sent to players per tick
  per-tick: 4
  #Radius of chunks that need to be sent before spawning the player
  spawn-radius: 4

chunk-ticking:
  #Max amount of chunks processed each tick
  per-tick: 40
  #Radius of chunks around a player to tick
  tick-radius: 3
  #Number of blocks inside ticking areas\' subchunks that get ticked every tick. Higher values will accelerate events
  #like tree and plant growth, but at a higher performance cost.
  blocks-per-subchunk-per-tick: 3
  #IDs of blocks not to perform random ticking on.
  disable-block-ticking:
    #- 2 # grass

chunk-generation:
  #Max. amount of chunks in the waiting queue to be populated
  population-queue-size: 32

ticks-per:
  autosave: 6000

auto-report:
  #Send crash reports for processing
  enabled: true
  send-code: true
  send-settings: true
  send-phpinfo: false
  use-https: true
  host: crash.pmmp.io

anonymous-statistics:
  #Sends anonymous statistics for data aggregation, plugin usage tracking
  enabled: false #TODO: re-enable this when we have a new stats host
  host: stats.pocketmine.net

auto-updater:
  enabled: true
  on-update:
    warn-console: true
  #Can be development, alpha, beta or stable.
  preferred-channel: beta
  #If using a development version, it will suggest changing the channel
  suggest-channels: true
  host: update.pmmp.io

timings:
  #Choose the host to use for viewing your timings results.
  host: timings.pmmp.io

console:
  #Choose whether to enable server stats reporting on the console title.
  #NOTE: The title ticker will be disabled regardless if console colours are not enabled.
  title-tick: true

aliases:
  #Examples:
  #showtheversion: version
  #savestop: [save-all, stop]

worlds:
  #These settings will override the generator set in server.properties and allows loading multiple levels
  #Example:
  #world:
  # seed: 404
  # generator: FLAT
  # preset: 2;bedrock,59xstone,3xdirt,grass;1

plugins:
  #Setting this to true will cause the legacy structure to be used where plugin data is placed inside the --plugins dir.
  #False will place plugin data under plugin_data under --data.
  #This option exists for backwards compatibility with existing installations.
  legacy-data-dir: false
',
  'extensions' =>
  array (
    'Core' => '8.0.11',
    'date' => '8.0.11',
    'libxml' => '8.0.11',
    'openssl' => '8.0.11',
    'pcre' => '8.0.11',
    'sqlite3' => '8.0.11',
    'zlib' => '8.0.11',
    'bcmath' => '8.0.11',
    'calendar' => '8.0.11',
    'chunkutils2' => '0.3.1',
    'crypto' => '0.3.2',
    'ctype' => '8.0.11',
    'curl' => '8.0.11',
    'dom' => '20031129',
    'fileinfo' => '8.0.11',
    'filter' => '8.0.11',
    'ftp' => '8.0.11',
    'gd' => '8.0.11',
    'gmp' => '8.0.11',
    'hash' => '8.0.11',
    'standard' => '8.0.11',
    'json' => '8.0.11',
    'leveldb' => '0.3.0',
    'libdeflate' => '0.1.0',
    'mbstring' => '8.0.11',
    'morton' => '0.1.2',
    'mysqlnd' => 'mysqlnd 8.0.11',
    'SPL' => '8.0.11',
    'pcntl' => '8.0.11',
    'mysqli' => '8.0.11',
    'PDO' => '8.0.11',
    'pdo_mysql' => '8.0.11',
    'pdo_sqlite' => '8.0.11',
    'Phar' => '8.0.11',
    'posix' => '8.0.11',
    'sockets' => '8.0.11',
    'pthreads' => '3.2.1dev',
    'recursionguard' => '0.1.0',
    'Reflection' => '8.0.11',
    'shmop' => '8.0.11',
    'SimpleXML' => '8.0.11',
    'igbinary' => '3.2.6',
    'tokenizer' => '8.0.11',
    'xml' => '8.0.11',
    'xmlreader' => '8.0.11',
    'xmlwriter' => '8.0.11',
    'yaml' => '2.2.1',
    'zip' => '1.19.4',
    'Zend OPcache' => '8.0.11',
  ),
)

dktapps commented 2 years ago

I'm surprised PHPStan doesn't detect this.

dktapps commented 2 years ago

This occurs when having a mixture of folder plugins and phar/script plugins. If DevTools loads before any of the other phar/script plugins available, this crash will occur. I never saw it in my local setup because all my plugins are in folder form apart from DevTools.

dktapps commented 2 years ago

Reported PHPStan issue as phpstan/phpstan#5848. Referenced commit fixes the crash (it didn't need value comparison anyway; the triage is already indexed by plugin names).