Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++ Extension Generator Inheriting from VoxelGeneratorScript crashes when "reloadable = true" in .gdextension #605

Open
stevenlgreen00 opened this issue Feb 25, 2024 · 16 comments
Labels
Needs more info Couldn't repro / more info needed Waiting for Godot Godot needs an improvement

Comments

@stevenlgreen00
Copy link

Hi just getting started with this tool.

My system:

  • Generator
  • Godot Git Tag 4.2.1-stable
  • Voxel Git Tag v1.1.0
  • Ubuntu 22.04
  • AMD 6600XT Gpu
  • Dev Build

I am testing out a custom generator inheriting from VoxelGeneratorScript.
I have my example generating a voxel flat terrain and it works within VoxelTerrain when normally used.

I am trying to see if I could get it to work with hot pluggable C++.
If I set "reloadable = true", within .gdextension, the godot engine crashes out.
I understand the "reloadable" flag enables hot plugging for C++ (feel free to correct me if I miss-understand).

I am still learning how to debug C++ in godot, but thought I would check and see if there is something special I need to
do to my extension so that it can handle the reload.

I've tried the flag with the built in generators and it seems to work fine. I also tried to implement a generator deriving from VoxelGenerator directly, but the versions I've made do not show up in the VoxelTexture's generators list.

Is there something special I need to add to my generator that derives from VoxelGeneratorScript to enable hot reloading?

Thank you,

Steve Green

@stevenlgreen00
Copy link
Author

I thought I would add some gdb data.
I get the following messages to error before a stack trace. They repeat beyond the length of my terminal buffer.

ERROR:` Condition "p_size < 0" is true. Returning: ERR_INVALID_PARAMETER
   at: resize (./core/templates/cowdata.h:265)
ERROR: Condition "err" is true. Returning: true
   at: push_back (./core/templates/vector.h:317)
ERROR: Condition "err" is true. Returning: true
   at: push_back (./core/templates/vector.h:317)

Here is the stack trace in case there are any hints. I'm still learning to debug the engine so I am not sure what to make of them as yet.

[1] /lib/x86_64-linux-gnu/libc.so.6(+0x42520) [0x7ffff7cc6520] (??:0)
[2] Error CowData<ObjectID>::resize<false>(int) (/home/work/AGWAN01/debug/godot-voxel/godot/./core/object/object_id.h:58 (discriminator 3))
[3] Vector<ObjectID>::push_back(ObjectID) (/home/work/AGWAN01/debug/godot-voxel/godot/./core/templates/vector.h:317)
[4] GDExtension::track_instance_binding(Object*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/extension/gdextension.cpp:1082)
[5] GDExtensionManager::track_instance_binding(void*, Object*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/extension/gdextension_manager.cpp:208)
[6] Object::get_instance_binding(void*, GDExtensionInstanceBindingCallbacks const*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/object/object.cpp:1861)
[7] /home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(+0x6060d33) [0x55555b5b4d33] (/home/work/AGWAN01/debug/godot-voxel/godot/core/extension/gdextension_interface.cpp:1146)
[8] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x16a2d) [0x7fffe6978a2d] (??:0)
[9] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x8545) [0x7fffe696a545] (??:0)
[10] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x8648) [0x7fffe696a648] (??:0)
[11] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x866a) [0x7fffe696a66a] (??:0)
[12] bool zylann::voxel::VoxelGeneratorScript::_gdvirtual__generate_block_call<false>(Ref<zylann::voxel::gd::VoxelBuffer>, Vector3i, int) (/home/work/AGWAN01/debug/godot-voxel/godot/./core/object/ref_counted.h:209 (discriminator 49))
[13] zylann::voxel::VoxelGeneratorScript::generate_block(zylann::voxel::VoxelGenerator::VoxelQueryData&) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/generators/voxel_generator_script.cpp:19)
[14] zylann::voxel::GenerateBlockTask::run_cpu_generation() (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/generators/generate_block_task.cpp:131)
[15] zylann::voxel::GenerateBlockTask::run(zylann::ThreadedTaskContext&) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/generators/generate_block_task.cpp:63)
[16] zylann::ThreadedTaskRunner::thread_func(zylann::ThreadedTaskRunner::ThreadData&) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/util/tasks/threaded_task_runner.cpp:352)
[17] zylann::ThreadedTaskRunner::thread_func_static(void*) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/util/tasks/threaded_task_runner.cpp:177)
[18] Thread::callback(unsigned long, Thread::Settings const&, void (*)(void*), void*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/os/thread.cpp:61)
[19] std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(unsigned long, Thread::Settings const&, void (*)(void*), void*), unsigned long, Thread::Settings, void (*)(void*), void*> > >::_M_run() (/usr/include/c++/11/bits/std_thread.h:211)
[20] /home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(+0x6454ff4) [0x55555b9a8ff4] (thread.o:?)
[21] /lib/x86_64-linux-gnu/libc.so.6(+0x94ac3) [0x7ffff7d18ac3] (??:0)
[22] /lib/x86_64-linux-gnu/libc.so.6(+0x126850) [0x7ffff7daa850] (??:0)
-- END OF BACKTRACE --

@Zylann
Copy link
Owner

Zylann commented Feb 25, 2024

I also tried to implement a generator deriving from VoxelGenerator directly,

That's not how the module expects generators to be added currently. Not sure why it doesnt appear in the list, but even if it did it wouldn't work properly.

Is there something special I need to add to my generator that derives from VoxelGeneratorScript to enable hot reloading?

As far as I know this is not related to this module. The module calls extensions/scripts the same way other Godot classes do. If Godot crashes that's either a GDExtension problem or a problem in your code. Maybe the reloading feature wasn't properly tested in this kind of situation where heavy multi-threading is involved.

From reading your call stack, the module tries to call your class, something happens in your code (which does not seem to have any debug symbols so it shows ????) then you're doing something that calls back into GDExtension back in Godot, and that crashes. As for the error, something tries to resize an array passing a negative size, so something got corrupted earlier.

Another possibility is that something you're doing in your code somehow messes up with reloading. But I can't really tell what it is because I'm not familiar to how that feature works, and I'm not using it myself. It could help to see your code as well, and which line crashes.

Yet another thing that could go south is if your generator is already being called in the editor while you trigger hot-reloading. That's something I already warn about with scripts, because I'm pretty sure Godot will crash if reloading is triggered at the same time threads are executing script/extension code. A lot of people dont use threads in their game so it's likely not being noticed, but this module uses threads a lot including its API (in case it matters, those are threads created with Godot's Thread class, so at the very least Godot might detect them, but not sure if that's useful in this case).

@stevenlgreen00
Copy link
Author

I'm unsure how to add the debug traces to the output in my extension. It is not compiled into the engine, rather loaded from a shared object in some way. The shared object is compiled separately using a godot-cpp extension. The code is mainly example type stuff that generates a flat plane in an SDF volume.

It may be as you surmise that the generator is already being called in the editor. It is only when the generator is added to the VoxelTexture generator field does it crash.

Note: I would expect the sdf_plane function in the generator could just be replaced with the value of "gy".

Header for my plane generator.

#ifndef SGVOXELGEN_H
#define SGVOXELGEN_H

#include <godot_cpp/classes/voxel_generator_script.hpp>
#include <godot_cpp/classes/voxel_buffer.hpp>

namespace godot {
    class SgVoxelGen : public VoxelGeneratorScript {
    GDCLASS(SgVoxelGen, VoxelGeneratorScript)

    protected:
        static void _bind_methods();

    public:
        SgVoxelGen();

        ~SgVoxelGen();

        void
        _generate_block(const Ref<VoxelBuffer> &out_buffer, const Vector3i &origin_in_voxels, int32_t lod) override;

        int32_t _get_used_channels_mask() const override;
    };
} //namespace godot

#endif

C++ of my generator.

#include "sg_voxel_gen.h"
#include "sg_math_sdf.h"
#include <godot_cpp/core/class_db.hpp>

using namespace godot;

void SgVoxelGen::_bind_methods() {
}

SgVoxelGen::SgVoxelGen() {
    // Initialize any variables here.
}

SgVoxelGen::~SgVoxelGen() {
    // Add your cleanup here.
}

void SgVoxelGen::_generate_block(const Ref<VoxelBuffer> &out_buffer, const Vector3i &origin, int32_t lod) {
    if (lod != 0)
        return;
    static const float QUANTIZED_SDF_16_BITS_SCALE = 0.002f;
    static const int CHANNEL_SDF = 1;
    static const int PLANE_Y = 0;
    const Vector3i bs = out_buffer->get_size();
    const int stride = 1 << lod;
    int gz = origin.z;
    for (int z = 0; z < bs.z; ++z, gz += stride) {
        int gx = origin.x;
        for (int x = 0; x < bs.x; ++x, gx += stride) {
            int gy = origin.y;
            for (int y = 0; y < bs.y; ++y, gy += stride) {
                float sdf = sdf_plane(Vector3(gx, gy, gz), Vector3(0, 1, 0), 0.0);
                out_buffer->set_voxel_f(sdf, x, y, z, CHANNEL_SDF);
            }
        } // for x
    } // for z
}

int32_t SgVoxelGen::_get_used_channels_mask() const {
    static const int CHANNEL_SDF = 1;
    return CHANNEL_SDF;
//	return VoxelGeneratorScript::_get_used_channels_mask();
}

The remaining files are godot-cpp boiler plate.

#include "register_types.h"
#include <gdextension_interface.h>
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp>

#include "sg_voxel_gen.h"
#include "sg_voxel_simple.h"
#include "sg_gen_terrain_perlin.h"

using namespace godot;

void initialize_gdextension_types(ModuleInitializationLevel p_level)
{
	if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
		return;
	}
	ClassDB::register_class<SgVoxelGen>();
	ClassDB::register_class<SgGenTerrainPerlin>();
}

void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
	if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
		return;
	}
}

extern "C"
{
	// Initialization
	GDExtensionBool GDE_EXPORT sgtools_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
	{
		GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
		init_obj.register_initializer(initialize_gdextension_types);
		init_obj.register_terminator(uninitialize_gdextension_types);
		init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);

		return init_obj.init();
	}
}
#ifndef EXAMPLE_REGISTER_TYPES_H
#define EXAMPLE_REGISTER_TYPES_H

void initialize_gdextension_types();
void uninitialize_gdextension_types();

#endif // EXAMPLE_REGISTER_TYPES_H

My .gdextension file.

[configuration]

reloadable = true
entry_symbol = "sgtools_library_init"
compatibility_minimum = "4.2"

[libraries]

macos.debug = "res:https://bin/macos/libsgtools.macos.template_debug.framework"
macos.release = "res:https://bin/macos/libsgtools.macos.template_release.framework"
windows.debug.x86_32 = "res:https://bin/windows/libsgtools.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "res:https://bin/windows/libsgtools.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res:https://bin/windows/libsgtools.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res:https://bin/windows/libsgtools.windows.template_release.x86_64.dll"
linux.debug.x86_64 = "res:https://bin/linux/libsgtools.linux.template_debug.dev.x86_64.so"
linux.release.x86_64 = "res:https://bin/linux/libsgtools.linux.template_release.x86_64.so"
linux.debug.arm64 = "res:https://bin/linux/libsgtools.linux.template_debug.arm64.so"
linux.release.arm64 = "res:https://bin/linux/libsgtools.linux.template_release.arm64.so"
linux.debug.rv64 = "res:https://bin/linux/libsgtools.linux.template_debug.rv64.so"
linux.release.rv64 = "res:https://bin/linux/libsgtools.linux.template_release.rv64.so"
android.debug.x86_64 = "res:https://bin/android/libsgtools.android.template_debug.x86_64.so"
android.release.x86_64 = "res:https://bin/android/libsgtools.android.template_release.x86_64.so"
android.debug.arm64 = "res:https://bin/android/libsgtools.android.template_debug.arm64.so"
android.release.arm64 = "res:https://bin/android/libsgtools.android.template_release.arm64.so"

@Zylann
Copy link
Owner

Zylann commented Feb 25, 2024

I'm unsure how to add the debug traces to the output in my extension

If you're using SCons there are options you can specify when building, dev_build=yes (I keep failing to find a reference docs of those options but I suppose they are the same as core Godot)

After a quick glance I don't see what could be wrong in your code. So perhaps reloading is the culprit. Your code is stateless so I wouldn't expect it to be caused by something you are doing in code
Make sure all generation has fully completed before you start hot-reloading, to exclude such possibility.

I had a quick look around GDExtensionManager in Godot and couldn't see any thread-safety primitives, which makes me wonder whether this is the cause of the issue.

Despite the feature being called "hot-reload" I think it has more to do with reloading the library while Godot is open, rather than being able to reload it while it runs. But I could be wrong, I dont use this feature.

@stevenlgreen00
Copy link
Author

stevenlgreen00 commented Feb 25, 2024

My extension is already built with dev_build=yes, so I am not sure how the loading is done such that it would apply the debug information. These are the same settings, minus the module params, I used to compile my version of Godot.

/usr/bin/scons -j 32 dev_build=yes platform=linux debug_symbols=yes optimize=debug compiledb=yes

The whole hot-reloading thing is new, so I imagine there are likely to be bugs. I can work on it without the hot reload as I imagined it. I was just hoping I would be able to build my plugin and have the changes show up automatically in the editor after I compiled changes, without needing to restart Godot.

Thanks for your help, I'm still determining how I want my process to work, while at the same time learning Godot.

Thanks for all your work on the Voxel project, I look forward to using it.

@Zylann
Copy link
Owner

Zylann commented Feb 25, 2024

[8] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x16a2d) [0x7fffe6978a2d] (??:0)
[9] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x8545) [0x7fffe696a545] (??:0)
[10] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x8648) [0x7fffe696a648] (??:0)
[11] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.template_debug.dev.x86_64.so(+0x866a) [0x7fffe696a66a] (??:0)

The absence of file locations suggests that somehow your backtrace is unable to pick up your debug symbols. If they are present then I don't know why. Also FYI the name template_ suggests you built a library for use in exported games, not testing in editor.

@stevenlgreen00
Copy link
Author

It looks like the default target was template, compiling things with target=editor, changed the the errors. Every time I run I get different errors. Here is the longest one I can see, unfortunately I don't know who called propagate_notification. I may try a few breakpoints a little later.

ERROR: Condition "!_get_alloc_size_checked(p_size, &alloc_size)" is true. Returning: ERR_OUT_OF_MEMORY
   at: resize (./core/templates/cowdata.h:285)
ERROR: Condition "err" is true. Returning: true
   at: push_back (./core/templates/vector.h:317)
ERROR: Caller thread can't call this function in this node (/root). Use call_deferred() or call_thread_group() instead.
   at: propagate_notification (scene/main/node.cpp:2236)

@stevenlgreen00
Copy link
Author

Well, I spent some time rummaging about this rabbit hole.

Stack traces seemed to lead me to "voxel_engine_updater" where I made a couple random changes to defer setting values, as some of the error messages indicated as a fix. It didn't appear to hurt in the editor, well not such I could notice, but all it did was push the crash to a new location.

I don't really understand the code, or Godot for that matter, well enough to be of much use. So I'll leave this alone for now and go back to my project. Getting a closer look at some of this was a fun aside, but not critical to me by any means.

Just for posterity, my hacks to VoxelEngineUpdater.

void VoxelEngineUpdater::ensure_existence(SceneTree *st) {
    if (st == nullptr) {
        return;
    }
    if (g_updater_created) {
        return;
    }
    Node *root = st->get_root();
    for (int i = 0; i < root->get_child_count(); ++i) {
        VoxelEngineUpdater *u = Object::cast_to<VoxelEngineUpdater>(root->get_child(i));
        if (u != nullptr) {
            return;
        }
    }
    VoxelEngineUpdater *u = memnew(VoxelEngineUpdater);
    //u->set_name("VoxelEngineUpdater_dont_touch_this");
    u->set_deferred("name","VoxelEngineUpdater_dont_touch_this");
    // TODO This can fail (for example if `Node::data.blocked > 0` while in `_ready()`) but Godot offers no API to check
    // anything. So if this fail, the node will leak.
    //root->add_child(u);
    root->call_deferred(SNAME("add_child"), u);
}

@Zylann
Copy link
Owner

Zylann commented Feb 25, 2024

    //u->set_name("VoxelEngineUpdater_dont_touch_this");
    u->set_deferred("name","VoxelEngineUpdater_dont_touch_this");

This change makes no sense. It should be possible to set the name right away.

    // TODO This can fail (for example if `Node::data.blocked > 0` while in `_ready()`) but Godot offers no API to check
    // anything. So if this fail, the node will leak.
    //root->add_child(u);
    root->call_deferred(SNAME("add_child"), u);

If you hit this issue, I'd like to know in which circumstance you are getting it (as in, what's the call stack when the error occurs). Because that should be completely unrelated to your issue as well

@stevenlgreen00
Copy link
Author

I was trying to isolate a crash that seemed to reoccur in propagate_notification and added code to print the stack-trace every time it entered that function. When it crashed at that function, giving a message indicating that the set_name function call should be deferred I followed the call stack back.

Honestly I was grasping at straws. I'll try to reproduce what was happening again and post it. I don't get a lot of stack traces, it usually bombs out in a malloc or memory alignment error.

I am not very experienced with multi-threaded code, so feel free to let me know if I do something stupid :)

@stevenlgreen00
Copy link
Author

Ok ran it a couple times in GDB.

In the second run (shown first), I got this, which traces back to to ensure_existence.

/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_Z11print_tracev+0x2c) [0x5555596eb11c]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN4Node22propagate_notificationEi+0xe5) [0x5555596f17ef]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN4Node8set_nameERK6String+0x185) [0x5555596f569b]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN6zylann5voxel18VoxelEngineUpdater16ensure_existenceEP9SceneTree+0xcf) [0x55555831de85]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN6zylann5voxel12VoxelTerrain13_notificationEi+0x365) [0x5555582e3a7f]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN6zylann5voxel12VoxelTerrain14_notificationvEib+0x1f) [0x5555582ea32f]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN6Object12notificationEib+0x34) [0x55555b5dfe72]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN9SceneTree14_process_groupEPNS_12ProcessGroupEb+0x8bb) [0x55555973940b]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN9SceneTree8_processEb+0xc67) [0x55555973ee2d]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN9SceneTree7processEd+0x1c5) [0x55555973f7b7]
realloc(): invalid next size

In the first run GDB actually produced a stack trace:

ERROR: Condition "p_size < 0" is true. Returning: ERR_INVALID_PARAMETER
ERROR: Condition "err" is true. Returning: true
   at: resize (./core/templates/cowdata.h:265)
   at: push_back (./core/templates/vector.h:317)
ERROR: Condition "err" is true. Returning: true
   at: push_back (./core/templates/vector.h:317)
ERROR: Condition "err" is true. Returning: true
   at: push_back (./core/templates/vector.h:317)
[1] /lib/x86_64-linux-gnu/libc.so.6(+0x42520) [0x7ffff7cc6520] (??:0)
[2] Error CowData<ObjectID>::resize<false>(int) (/home/work/AGWAN01/debug/godot-voxel/godot/./core/object/object_id.h:58 (discriminator 3))
[3] Vector<ObjectID>::push_back(ObjectID) (/home/work/AGWAN01/debug/godot-voxel/godot/./core/templates/vector.h:317)
[4] GDExtension::track_instance_binding(Object*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/extension/gdextension.cpp:1082)
[5] GDExtensionManager::track_instance_binding(void*, Object*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/extension/gdextension_manager.cpp:208)
[6] Object::get_instance_binding(void*, GDExtensionInstanceBindingCallbacks const*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/object/object.cpp:1861)
[7] /home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(+0x6060e33) [0x55555b5b4e33] (/home/work/AGWAN01/debug/godot-voxel/godot/core/extension/gdextension_interface.cpp:1146)
[8] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.editor.dev.x86_64.so(+0x16a2d) [0x7fffe6978a2d] (??:0)
[9] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.editor.dev.x86_64.so(+0x8545) [0x7fffe696a545] (??:0)
[10] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.editor.dev.x86_64.so(+0x8648) [0x7fffe696a648] (??:0)
[11] /home/work/AGWAN01/godot-projects/Agwan01/bin/linux/libsgtools.linux.editor.dev.x86_64.so(+0x866a) [0x7fffe696a66a] (??:0)
[12] bool zylann::voxel::VoxelGeneratorScript::_gdvirtual__generate_block_call<false>(Ref<zylann::voxel::gd::VoxelBuffer>, Vector3i, int) (/home/work/AGWAN01/debug/godot-voxel/godot/./core/object/ref_counted.h:209 (discriminator 49))
[13] zylann::voxel::VoxelGeneratorScript::generate_block(zylann::voxel::VoxelGenerator::VoxelQueryData&) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/generators/voxel_generator_script.cpp:19)
[14] zylann::voxel::GenerateBlockTask::run_cpu_generation() (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/generators/generate_block_task.cpp:131)
[15] zylann::voxel::GenerateBlockTask::run(zylann::ThreadedTaskContext&) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/generators/generate_block_task.cpp:63)
[16] zylann::ThreadedTaskRunner::thread_func(zylann::ThreadedTaskRunner::ThreadData&) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/util/tasks/threaded_task_runner.cpp:352)
[17] zylann::ThreadedTaskRunner::thread_func_static(void*) (/home/work/AGWAN01/debug/godot-voxel/modules/voxel/util/tasks/threaded_task_runner.cpp:177)
[18] Thread::callback(unsigned long, Thread::Settings const&, void (*)(void*), void*) (/home/work/AGWAN01/debug/godot-voxel/godot/core/os/thread.cpp:61)
[19] std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(unsigned long, Thread::Settings const&, void (*)(void*), void*), unsigned long, Thread::Settings, void (*)(void*), void*> > >::_M_run() (/usr/include/c++/11/bits/std_thread.h:211)
[20] /home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(+0x64550f4) [0x55555b9a90f4] (thread.o:?)
[21] /lib/x86_64-linux-gnu/libc.so.6(+0x94ac3) [0x7ffff7d18ac3] (??:0)
[22] /lib/x86_64-linux-gnu/libc.so.6(+0x126850) [0x7ffff7daa850] (??:0)
-- END OF BACKTRACE --

@stevenlgreen00
Copy link
Author

With my changes in place this is where it dies, but also doesn't want to give me a stack trace.

Obtained 10 stack frames.
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_Z11print_tracev+0x2c) [0x5555596eb2b6]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN4Node22propagate_notificationEi+0xe5) [0x5555596f1989]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN4Node8set_nameERK6String+0x185) [0x5555596f5835]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_Z29call_with_variant_args_helperI17__UnexistingClassJRK6StringEJLm0EEEvPT_MS4_FvDpT0_EPPK7VariantRN8Callable9CallErrorE13IndexSequenceIJXspT1_EEE+0x84) [0x555557628574]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_Z25call_with_variant_args_dvI17__UnexistingClassJRK6StringEEvPT_MS4_FvDpT0_EPPK7VariantiRN8Callable9CallErrorERK6VectorISA_E+0x195) [0x555557628735]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZNK11MethodBindTIJRK6StringEE4callEP6ObjectPPK7VariantiRN8Callable9CallErrorE+0x25) [0x555557628765]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN7ClassDB12set_propertyEP6ObjectRK10StringNameRK7VariantPb+0x26b) [0x55555b5c226f]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN6Object3setERK10StringNameRK7VariantPb+0x82) [0x55555b5e5828]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN9CallQueue5flushEv+0x316) [0x55555b5deb0a]
/home/work/AGWAN01/debug/godot-voxel/godot/bin/godot.linuxbsd.editor.dev.x86_64(_ZN9SceneTree7processEd+0x20d) [0x55555973f999]
malloc(): unaligned tcache chunk detected

@Zylann
Copy link
Owner

Zylann commented Feb 26, 2024

In the second run (shown first), I got this, which traces back to to ensure_existence.

That failure is nonsensical. It rather sounds like the memory allocator got corrupted by your hot-reloading issue, because that piece of code is completely unrelated. I'm not even sure why that code runs when you hot-reload because if you had a terrain in the open scene, that code will have already run once and would never need to run again.

@stevenlgreen00
Copy link
Author

No problem, it was just a shot in the dark. Gdb, wasn't giving me much to go on so I tried a few print statements. But it is at the very least consistent, it creates the same traces then dies in a memory routine.

I'm not sure what the hot reload does or even how it loads the extensions. I read in blog post that it runs when the window focus changes. I'm wondering if it just keeps reloading things, or what it is really doing in the editor. A long time ago I loaded shared objects programmatically, but I only vaguely remember the APIs. If I have time in the future I may browse the code in depth to at least see how the loader works.

@Zylann Zylann added Waiting for Godot Godot needs an improvement Needs more info Couldn't repro / more info needed labels Feb 26, 2024
@Zylann
Copy link
Owner

Zylann commented Feb 26, 2024

Either way at this point this should be reported somehow to GDExtension devs, not the module, but I'm not even sure how that report should look like, because right now a repro would pretty much require my module and your extension.
I asked on Godot dev chat in case someone is around to give some info.

@stevenlgreen00
Copy link
Author

I could probably write something up and submit to them. It is getting a little late for me today, so I can do it tomorrow. I could also bounce it off the thread discussing hot-reloading as well and get their thoughts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs more info Couldn't repro / more info needed Waiting for Godot Godot needs an improvement
Projects
None yet
Development

No branches or pull requests

2 participants