godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.43k stars 21.06k forks source link

Segfault when running PCK from older Godot version with newer Server binary #29084

Open menip opened 5 years ago

menip commented 5 years ago

Godot version: 3.1

OS/device including version: Ubuntu 18.04

Issue description: Running a 3.1 export .pck using 3.1.1 server binary results in segfault without message as to why.

Original issue: Game server runs fine in editor and as exported executable, but not when running .pck file via server binary. I have game client and server. In editor both run fine, exported and executed directly, both run fine. However when using the server template from https://godotengine.org/download/server I get segfault.

Minimal reproduction project: Can follow the original ones. The server .pck provided was exported using 3.1-stable, and if run with official 3.1.1 server binary you'll see segfault. What's curious is as far as I can tell, you still have to click the "Lets go" button on client to trigger crash.

Original steps: Not sure what issue is, so included my client/server in addition to exports of both. Instructions in zip on how to run and achieve segfault. Note if you want to export my project, be sure to include *.json resources.

Zip for download at https://menip.itch.io/deathmatch. Password is "godot"

Calinou commented 5 years ago

I can confirm this in the example project when running a self-compiled server binary built from commit https://github.com/godotengine/godot/commit/e2375f487c2b6857ba7300ed1d460f43cef8cc59. The segfault only occurs when using DeathMatch Server.pck as a main pack, not DeathMatch.pck.

menip commented 5 years ago

@Calinou Thanks for confirm! Good to know it's not just my system. I hadn't considered running client with server binary, but also good to know it's unaffected.

menip commented 5 years ago

Something I noticed was I'm using Godot 3.1, but server binary provided is 3.1.1. Compiling server binary from 3.1-stable and everything works great! Compiling server binary from e2375f4 results in unrelated crash. Assuming something about how scripts are parsed. Exporting game client and server using official 3.1.1 binary and running server with official server binary results in correct behavior.

Issue seems to of therefore been due to user error. As such, I will close this issue within the next several days. I'm not sure why a minor version change would result in segfault. It may also be useful to print message when have mismatch between .pck and binary versions.

KoBeWi commented 3 years ago

Can anyone still reproduce this bug in Godot 3.2.3 or any later release?

menip commented 3 years ago

@KoBeWi Just tested with a project exported via 3.1.1. Runs fine on 3.1.1 server binary, seg faults on 3.2.3. No error message is provided.

akien-mga commented 3 years ago

To clarify, it's normal that a PCK exported with an older Godot version might not work with a newer version. If there's any change in the parsing of scenes, resources or GDScript bytecode (the latter being the most likely), the game will error out.

It should not segfault though, but throw a bunch of errors. In this case I can confirm that the server build does segfault instead of throwing errors, which is the issue that should be fixed.

This is from running with my distro-provided server (headless) binary for 3.2.3-stable.

Thread 1 "godot-server" received signal SIGSEGV, Segmentation fault.
0x0000000000852080 in GDScriptFunctions::call(GDScriptFunctions::Function, Variant const**, int, Variant&, Variant::CallError&) ()
(gdb) bt
#0  0x0000000000852080 in GDScriptFunctions::call(GDScriptFunctions::Function, Variant const**, int, Variant&, Variant::CallError&) ()
#1  0x0000000000856c66 in GDScriptParser::_reduce_expression(GDScriptParser::Node*, bool) ()
#2  0x00000000008569bb in GDScriptParser::_reduce_expression(GDScriptParser::Node*, bool) ()
#3  0x00000000008569bb in GDScriptParser::_reduce_expression(GDScriptParser::Node*, bool) ()
#4  0x0000000000861076 in GDScriptParser::_parse_and_reduce_expression(GDScriptParser::Node*, bool, bool, bool) ()
#5  0x0000000000862e05 in GDScriptParser::_parse_block(GDScriptParser::BlockNode*, bool) ()
#6  0x0000000000863542 in GDScriptParser::_parse_block(GDScriptParser::BlockNode*, bool) ()
#7  0x0000000000867df7 in GDScriptParser::_parse_class(GDScriptParser::ClassNode*) ()
#8  0x0000000000890dec in GDScriptParser::_parse(String const&) ()
#9  0x000000000082a3fc in GDScript::load_byte_code(String const&) ()
#10 0x000000000082ca78 in ResourceFormatLoaderGDScript::load(String const&, String const&, Error*) ()
#11 0x0000000001701726 in ResourceLoader::_load(String const&, String const&, String const&, bool, Error*) [clone .constprop.0] ()
#12 0x0000000001611517 in ResourceLoader::load(String const&, String const&, bool, Error*) ()
#13 0x000000000065b440 in Main::start() ()
#14 0x0000000000637e5c in main ()
akien-mga commented 3 years ago

Here's the output from running the same PCK with a normal (non headless) X11 editor build:-

$ godot --main-pack DeathMatch_Server.pck        
Godot Engine v3.2.3.stable.mageia - https://godotengine.org
OpenGL ES 2.0 Renderer: Mesa Intel(R) HD Graphics 630 (KBL GT2)
OpenGL ES 2.0 Batching: ON

SCRIPT ERROR: GDScript::load_byte_code: Parse Error: Too few arguments for 'range_lerp' intrinsic function.
   At: res://ScriptsGlobal/gamestate.gdc:74.
ERROR: load_byte_code: Method failed. Returning: ERR_PARSE_ERROR
   At: modules/gdscript/gdscript.cpp:801.
ERROR: load: Cannot load byte code from file 'res://ScriptsGlobal/gamestate.gdc'.
   At: modules/gdscript/gdscript.cpp:2282.
ERROR: _load: Failed loading resource: res://ScriptsGlobal/gamestate.gdc. Make sure resources have been imported by opening the project in the editor at least once.
   At: core/io/resource_loader.cpp:278.
ERROR: start: Can't autoload: res://ScriptsGlobal/gamestate.gd
   At: main/main.cpp:1757.
SCRIPT ERROR: GDScript::load_byte_code: Parse Error: The class "Gaussian" conflicts with the AutoLoad singleton of the same name, and is therefore redundant. Remove the class_name declaration to fix this error.
   At: res://ScriptsGlobal/Gaussian.gdc:4.
ERROR: load_byte_code: Method failed. Returning: ERR_PARSE_ERROR
   At: modules/gdscript/gdscript.cpp:801.
ERROR: load: Cannot load byte code from file 'res://ScriptsGlobal/Gaussian.gdc'.
   At: modules/gdscript/gdscript.cpp:2282.
ERROR: _load: Failed loading resource: res://ScriptsGlobal/Gaussian.gdc. Make sure resources have been imported by opening the project in the editor at least once.
   At: core/io/resource_loader.cpp:278.
ERROR: start: Can't autoload: res://ScriptsGlobal/Gaussian.gd
   At: main/main.cpp:1757.
SCRIPT ERROR: GDScript::load_byte_code: Parse Error: Too few arguments for 'range_lerp' intrinsic function.
   At: res://World/World.gdc:150.
ERROR: load_byte_code: Method failed. Returning: ERR_PARSE_ERROR
   At: modules/gdscript/gdscript.cpp:801.
ERROR: load: Cannot load byte code from file 'res://World/World.gdc'.
   At: modules/gdscript/gdscript.cpp:2282.
ERROR: _load: Failed loading resource: res://World/World.gdc. Make sure resources have been imported by opening the project in the editor at least once.
   At: core/io/resource_loader.cpp:278.
ERROR: poll: res://World/World.tscn:3 - Parse Error: [ext_resource] referenced nonexistent resource at: res://World/World.gd
   At: scene/resources/resource_format_text.cpp:440.
ERROR: load: Failed to load resource 'res://World/World.tscn'.
   At: core/io/resource_loader.cpp:208.
ERROR: _load: Failed loading resource: res://World/World.tscn. Make sure resources have been imported by opening the project in the editor at least once.
   At: core/io/resource_loader.cpp:278.
ERROR: start: Failed loading scene: res://World/World.tscn
   At: main/main.cpp:1944.
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112.
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112.
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112.
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112.
WARNING: cleanup: ObjectDB instances leaked at exit (run with --verbose for details).
   At: core/object.cpp:2135.
ERROR: clear: Resources still in use at exit (run with --verbose for details).
   At: core/resource.cpp:477.

The output is not pretty but that's outside the scope of this issue, here it behaves as expected (has errors due to GDScript bytecode being incompatible, and fails to error out nicely so it leaks memory, which is a separate error - but might be related to why the headless build crashes).