Skip to content

Panic when calling deferred reload through new typed API #1249

@sylbeth

Description

@sylbeth

So, my build plugin is made with godot-rust, and it seems like GDExtensionManager's reload extension is incompatible when reloading the library it's being called from. This does make a lot of sense intuitively as the gdextension is still performing work inside that closure, but I thought it would be sensible to report it anyway. Here is the error message, but I don't know how to access anything else:

panicked at C:\Users\Sylbeth\scoop\persist\rustup\.cargo\git\checkouts\gdext-067f4b88e7bd088f\517053d\godot-core\src\private.rs:367:49:

thread panicked while processing panic. aborting.

The code for the build plugin's reloading I have here:

//! Build plugin, to manage the build script.

use std::sync::atomic::{AtomicBool, Ordering};

use godot::{
    classes::{
        EditorPlugin, GDExtensionManager, IEditorPlugin, editor_plugin::CustomControlContainer,
    },
    global::{godot_print, godot_str},
    obj::{Base, WithBaseField, WithDeferredCall},
    prelude::{GodotClass, godot_api},
};

use buttons::{BuildButtons, construct_build_buttons};

pub mod buttons;
pub mod commands;

static MUST_RELOAD: AtomicBool = AtomicBool::new(false);

/// A plugin that adds buttons for the ease of this gdext compilation.
#[derive(GodotClass)]
#[class(tool, init, base=EditorPlugin)]
pub struct BuildPlugin {
    /// Buttons loaded by the plugin.
    buttons: Option<BuildButtons>,

    /// Base class of the node.
    base: Base<EditorPlugin>,
}

#[godot_api]
impl IEditorPlugin for BuildPlugin {
    fn enter_tree(&mut self) {
        let buttons = construct_build_buttons();
        for button in buttons.iter() {
            self.base_mut()
                .add_control_to_container(CustomControlContainer::TOOLBAR, button);
        }
        self.buttons = Some(buttons);
    }

    fn ready(&mut self) {
        godot_print!("BuildPlugin: Ready!");
    }

    fn process(&mut self, _delta: f32) {
        if MUST_RELOAD.swap(false, Ordering::Acquire) {
            GDExtensionManager::singleton().apply_deferred(|gdextension_manager| {
                godot_print!("BuildPlugin: Reloading GDExtension.");
                gdextension_manager
                    .reload_extension(&godot_str!("res://{}", env!("GDEXTENSION-FILE-PATH")));
            });
        }
    }

    fn exit_tree(&mut self) {
        if let Some(buttons) = std::mem::replace(&mut self.buttons, None) {
            for button in buttons {
                self.base_mut()
                    .remove_control_from_container(CustomControlContainer::TOOLBAR, &button);
                button.free();
            }
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    quality-of-lifeNo new functionality, but improves ergonomics/internals

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions