Skip to content

Commit c7a5e66

Browse files
committed
Remove ExtensionLibrary::override_hot_reload()
This API is rather complex to use, and there's no indication that the customization is needed. If the need arises again, we should first consider improving the default behavior (e.g. Godot Editor/Export builds rather than Rust Debug/Release).
1 parent 4a6f803 commit c7a5e66

File tree

2 files changed

+43
-54
lines changed

2 files changed

+43
-54
lines changed

godot-core/src/init/mod.rs

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ pub unsafe fn __gdext_load_library<E: ExtensionLibrary>(
3131
// cause TLS-destructors to run then we have a setting already for how to deal with them. Otherwise, this could cause the default
3232
// behavior to kick in and disable hot reloading.
3333
#[cfg(target_os = "linux")]
34-
match E::override_hot_reload() {
35-
None => sys::linux_reload_workaround::default_set_hot_reload(),
36-
Some(true) => sys::linux_reload_workaround::enable_hot_reload(),
37-
Some(false) => sys::linux_reload_workaround::disable_hot_reload(),
38-
}
34+
sys::linux_reload_workaround::default_set_hot_reload();
3935

4036
let tool_only_in_editor = match E::editor_run_behavior() {
4137
EditorRunBehavior::ToolClassesOnly => true,
@@ -323,20 +319,6 @@ pub unsafe trait ExtensionLibrary {
323319
fn override_wasm_binary() -> Option<&'static str> {
324320
None
325321
}
326-
327-
/// Whether to enable hot reloading of this library. Return `None` to use the default behavior.
328-
///
329-
/// Enabling this will ensure that the library can be hot reloaded. If this is disabled then hot reloading may still work, but there is no
330-
/// guarantee. Enabling this may also lead to memory leaks, so it should not be enabled for builds that are intended to be final builds.
331-
///
332-
/// By default, this is enabled for debug builds and disabled for release builds.
333-
///
334-
/// Note that this is only checked *once* upon initializing the library. Changing this from `true` to `false` will be picked up as the
335-
/// library is then fully reloaded upon hot-reloading, however changing it from `false` to `true` is almost certainly not going to work
336-
/// unless hot-reloading is already working regardless of this setting.
337-
fn override_hot_reload() -> Option<bool> {
338-
None
339-
}
340322
}
341323

342324
/// Determines if and how an extension's code is run in the editor.

godot-ffi/src/linux_reload_workaround.rs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,41 +15,48 @@
1515
use std::ffi::c_void;
1616
use std::sync::OnceLock;
1717

18-
pub type ThreadAtexitFn = unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void);
19-
2018
static SYSTEM_THREAD_ATEXIT: OnceLock<Option<ThreadAtexitFn>> = OnceLock::new();
2119
static HOT_RELOADING_ENABLED: OnceLock<bool> = OnceLock::new();
2220

23-
fn system_thread_atexit() -> &'static Option<ThreadAtexitFn> {
24-
SYSTEM_THREAD_ATEXIT.get_or_init(|| unsafe {
25-
let name = c"__cxa_thread_atexit_impl".as_ptr();
26-
std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, name))
27-
})
28-
}
29-
30-
pub fn enable_hot_reload() {
31-
// If hot reloading is enabled then we should properly unload the library, so this will only be called once.
32-
HOT_RELOADING_ENABLED
33-
.set(true)
34-
.expect("hot reloading should only be set once")
35-
}
36-
37-
pub fn disable_hot_reload() {
38-
// If hot reloading is disabled then we may call this method multiple times.
39-
_ = HOT_RELOADING_ENABLED.set(false)
40-
}
41-
4221
pub fn default_set_hot_reload() {
4322
// By default, we enable hot reloading for debug builds, as it's likely that the user may want hot reloading in debug builds.
4423
// Release builds however should avoid leaking memory, so we disable hot reloading support by default.
24+
// In the future, this might consider the .gdextension `is_reloadable` flag, or whether Godot is using an editor or export build.
4525
if cfg!(debug_assertions) {
4626
enable_hot_reload()
4727
} else {
4828
disable_hot_reload()
4929
}
5030
}
5131

52-
fn is_hot_reload_enabled() -> bool {
32+
// ----------------------------------------------------------------------------------------------------------------------------------------------
33+
// Publicly accessible
34+
35+
#[macro_export]
36+
macro_rules! register_hot_reload_workaround {
37+
() => {
38+
#[no_mangle]
39+
#[doc(hidden)]
40+
pub unsafe extern "C" fn __cxa_thread_atexit_impl(
41+
func: *mut ::std::ffi::c_void,
42+
obj: *mut ::std::ffi::c_void,
43+
dso_symbol: *mut ::std::ffi::c_void,
44+
) {
45+
$crate::linux_reload_workaround::thread_atexit(func, obj, dso_symbol);
46+
}
47+
};
48+
}
49+
50+
type ThreadAtexitFn = unsafe extern "C" fn(*mut c_void, *mut c_void, *mut c_void);
51+
52+
pub fn system_thread_atexit() -> &'static Option<ThreadAtexitFn> {
53+
SYSTEM_THREAD_ATEXIT.get_or_init(|| unsafe {
54+
let name = c"__cxa_thread_atexit_impl".as_ptr();
55+
std::mem::transmute(libc::dlsym(libc::RTLD_NEXT, name))
56+
})
57+
}
58+
59+
pub fn is_hot_reload_enabled() -> bool {
5360
// Assume hot reloading is disabled unless something else has been specified already. This is the better default as thread local storage
5461
// destructors exist for good reasons.
5562
// This is needed for situations like unit-tests, where we may create TLS-destructors without explicitly calling any of the methods
@@ -78,17 +85,17 @@ pub unsafe fn thread_atexit(func: *mut c_void, obj: *mut c_void, dso_symbol: *mu
7885
}
7986
}
8087

81-
#[macro_export]
82-
macro_rules! register_hot_reload_workaround {
83-
() => {
84-
#[no_mangle]
85-
#[doc(hidden)]
86-
pub unsafe extern "C" fn __cxa_thread_atexit_impl(
87-
func: *mut ::std::ffi::c_void,
88-
obj: *mut ::std::ffi::c_void,
89-
dso_symbol: *mut ::std::ffi::c_void,
90-
) {
91-
$crate::linux_reload_workaround::thread_atexit(func, obj, dso_symbol);
92-
}
93-
};
88+
// ----------------------------------------------------------------------------------------------------------------------------------------------
89+
// Implementation
90+
91+
fn enable_hot_reload() {
92+
// If hot reloading is enabled then we should properly unload the library, so this will only be called once.
93+
HOT_RELOADING_ENABLED
94+
.set(true)
95+
.expect("hot reloading should only be set once")
96+
}
97+
98+
fn disable_hot_reload() {
99+
// If hot reloading is disabled then we may call this method multiple times.
100+
_ = HOT_RELOADING_ENABLED.set(false)
94101
}

0 commit comments

Comments
 (0)