Prevent re-entrant script class update mutation - #5
Open
dsarno wants to merge 710 commits into
Open
Conversation
SCons: Drop VS2017 support, use C17 universally
…ion-preview Import: Fix generated collision preview
…inding-refresh-on-rename Fix missing name refresh on bindings when changing the OpenXR action map.
…gative-timescale Fix negative time scale regression in BlendSpace1D and BlendSpace2D
Fix undo crash when animation editor is not active
Update layer selector when modifying the `TileMap` in the inspector
Add error to error messages in `FileAccessPack`
…shift_enter Add Shift+Enter and Shift+KpEnter as default shortcuts for newline
…andling-reprojected Filter and sanitize volumetric fog to stop invalid values flooding the screen with black pixels through temporal reprojection.
…scription Fix item focused signal description
…t-textures Fix GPU validation errors due to area light LUT format
…invert-mess-det-something-something Fix error when CPUParticles3D has `scale` set to `(0, 0, 0)`
Animation: Only erase properties for a specific node
Fixes an issue with not being able to set overrun behaviour on tags without the button size zeroing out.
…-clear-button Improve 'Clear Output' button position
Editor: Fix Tag Overrun Behavior
Fix audio bus name update
Dependency editor: fix label, it's the owners, not the dependencies of files to delete
Add cleanup of `EditorInspector` clipboard contents
…pestring_typo Fix typo in C# string interpolation in `TYPE_STRING` doc
dr_mp3: Update to 0.7.3
…tor-tooltips Fix inspector tooltips after focus changes
Expose `_can_commit_handle_on_click()`
Fix `PopupMenu` submenu positioning not accounting for margins
…l_params Fix shader crash when using parameter name identical to uniform name
…be-interpolation-at-lightmap-edges Fix LightmapGI probe interpolation at lightmap AABB edges
Fix ordering of notes in the description of the `seed()` function in `RandomNumberGenerator`
The `Engine::Singleton` struct stores a raw `Object *`, so registering a `RefCounted` only works if some external `Ref<>` keeps it alive. This pattern is fragile and can lead to UB, especially with GDExtension.
- Fixes https://play.google.com/console/u/0/developers/5310120689138741555/app/4972363226496209566/vitals/crashes/6747aea8b031aa6718dfd3909b7c2879/details?days=28&isUserPerceived=true&versionCode=40700105 - Fixes https://play.google.com/console/u/0/developers/5310120689138741555/app/4972363226496209566/vitals/crashes/0f8b9c9f9936f3b8e7027940a99a5c85/details?days=28&isUserPerceived=true&versionCode=40700105
…ror_fix Fix error spam when resizing a control in a zero size parent with anchors mode enabled
…aught_me_offguard_in_my_own_project Fix wrong path in `EditorExportPlugin._export_begin()` when zipping
…u_got_there Fix various editor state related regressions
…_fix Fix misaligned timeline indicator on the Bezier editor
Wayland: Fix incorrect fallback value for height in _xdg_popup_on_configure
[Android] Fix reported crashes from the Play store
…t3d-throwing-!is_inside_tree() Fix `BoneAttachment3D` throws `!is_inside_tree()`
…ine-redesign Improve inline shader preview layout
Phase out `RefCounted` singletons as UB pitfalls
…lete Suppress GCC 16's `sfinae-incomplete` warning
[Accessibility] Do not set duplicate values for editor inspector elements.
There was a problem hiding this comment.
Pull request overview
This PR fixes a crash class of re-entrant mutations in EditorFileSystem pending script update containers by preventing recursive processing while an outer update pass is still iterating, which can occur when EditorProgress pumps Main::iteration() via the editor UI.
Changes:
- Drain
update_script_paths/update_script_paths_documentationinto local containers before creatingEditorProgressand iterating, preventing re-entrant mutation of the live pending containers. - Add
_process_update_pending()re-entry guarding with a queued-rerun mechanism to defer nested update requests to a later pass instead of recursing. - Route the pre-reimport “update script classes first” path through the same guarded mechanism while preserving ordering.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| editor/file_system/editor_file_system.h | Adds re-entry guard state and updates _process_update_pending signature to support class-only processing. |
| editor/file_system/editor_file_system.cpp | Drains pending containers before iteration and introduces guarded, rerunnable pending-update processing to prevent re-entrant mutation crashes. |
Comments suppressed due to low confidence (1)
editor/file_system/editor_file_system.cpp:2217
- Similar to the script class updates,
script_paths_to_update_documentation = update_script_paths_documentation; update_script_paths_documentation.clear();copies the whole HashSet and then clears the original. If this set can get large, consider draining it via move/swap under the mutex to avoid O(n) copying/allocation churn (HashSet has move assignment available incore/templates/hash_set.h).
HashSet<String> script_paths_to_update_documentation;
{
MutexLock update_script_lock(update_script_mutex);
script_paths_to_update_documentation = update_script_paths_documentation;
update_script_paths_documentation.clear();
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+2166
to
+2167
| script_paths_to_update = update_script_paths; | ||
| update_script_paths.clear(); |
dsarno
force-pushed
the
fix/editor-filesystem-script-class-reentry
branch
2 times, most recently
from
May 16, 2026 05:19
c2f378b to
9e47ae9
Compare
dsarno
force-pushed
the
fix/editor-filesystem-script-class-reentry
branch
from
May 16, 2026 05:33
9e47ae9 to
e2daef8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
This is related to the
Task 'update_scripts_classes' already existssymptom reported in godotengine#115460, but fixes the issue from theEditorFileSystemside. It does not changeProgressDialogbehavior globally.This was found while developing and stress testing
godot-ai, which exercises editor automation paths that repeatedly update tool scripts during editor startup. The minimal repro reduces that workload to a small@toolscript that callsEditorFileSystem.update_file()during editor processing:https://github.com/dsarno/godot-115460-gdscript-repro
EditorFileSystem::_update_script_classes()and_update_script_documentation()createEditorProgresstasks when more than one script is pending. In the GUI editor,EditorProgresscan pumpMain::iteration()throughProgressDialog::_update_ui().That nested editor frame can run
@toolscript code and recursively enter pending script update processing while the outer pass is still active. For script class updates, this lets an inner_update_script_classes()mutate or clearupdate_script_pathswhile an outer_update_script_classes()range loop is still iterating it.The crash can surface later while registering/removing global classes, but the corrupting invariant is the re-entrant mutation of the live pending container. The same re-entry path can also duplicate the documentation progress task.
Fix
update_script_pathsinto a localHashMapbefore creatingEditorProgressor iterating script class updates.update_script_paths_documentationinto a localHashSetbefore creating its progress task._process_update_pending()re-entry guard with a pending-rerun bit, so updates queued by nested editor frames are preserved for a later pass instead of being processed recursively.If a tool script continuously queues new script class updates during every pumped editor frame, documentation updates can still be delayed until that update stream settles. This PR keeps the fix scoped to pending script update processing instead of changing progress dialog behavior globally.
Testing
Built locally:
Focused doctest suites:
bin/godot.macos.editor.dev.arm64 --headless --test --test-suite='*[GDScript]*,*[Editor]*'Result: 6 test cases passed, 58,688 assertions passed.
Regression repro verification with the MRP linked above:
GENERATED_SCRIPT_COUNT := 2,MAX_TICKS := 80: finished without crash, no duplicateupdate_scripts_classes, no duplicateupdate_script_paths_documentation, no!tasks.hasassertion.GENERATED_SCRIPT_COUNT := 2,MAX_TICKS := 0: smooth editor load, finished without crash,max_re_entry=1.GENERATED_SCRIPT_COUNT := 1, headless control: finished without crash,max_re_entry=1.No automated regression test is included because the proven failure mechanism requires GUI
ProgressDialogpumpingMain::iteration()during editor filesystem processing. The current headless doctest harness does not directly exercise that GUI progress re-entry path without a synthetic editor integration harness.