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

Preloading a scene containing materials causes deadlock in SpinLock through material_owner.owns(p_rid) in RendererStorageRD::free #49201

Closed
HaSa1002 opened this issue May 30, 2021 · 6 comments · Fixed by #50193

Comments

@HaSa1002
Copy link
Contributor

HaSa1002 commented May 30, 2021

Godot version:
9f37456

OS/device including version:
Windows 10, 19042.928
Vulkan Device: AMD Radeon RX 580 (Driver 20.12.1)
Built with MSVC 14.2

Issue description:
When you try to open the attached project Godot just hangs. This happend to me as I tried to port a project from 3.x to 4.0. I attached Visual Studio and paused the execution. The execution stopps there https://github.com/godotengine/godot/blob/master/servers/rendering/renderer_rd/renderer_storage_rd.cpp#L8606 (material_owner.owns(p_rid)). Following the code you find your code locked by a SpinLock. This is even more interesting as I got the following Stacktrace:

Stack Trace
godot.windows.opt.tools.64.exe!RendererStorageRD::free(RID p_rid) Line 8606	C++
godot.windows.opt.tools.64.exe!RenderingServerDefault::_free(RID p_rid) Line 68	C++
[Inlineframe] godot.windows.opt.tools.64.exe!CommandQueueMT::flush_one(bool) Line 461	C++
godot.windows.opt.tools.64.exe!CommandQueueMT::flush_all() Line 509	C++
[Inlineframe] godot.windows.opt.tools.64.exe!CommandQueueMT::flush_if_pending() Line 503	C++
godot.windows.opt.tools.64.exe!RenderingServerDefault::free(RID p_rid) Line 900	C++
[Inlineframe] godot.windows.opt.tools.64.exe!GradientTexture::{dtor}() Line 1517	C++
godot.windows.opt.tools.64.exe!GradientTexture::`scalar deleting destructor'(unsigned int)	C++
godot.windows.opt.tools.64.exe!memdelete<Object>(Object * p_class) Line 118	C++
godot.windows.opt.tools.64.exe!Variant::_clear_internal() Line 1311	C++
[Inlineframe] godot.windows.opt.tools.64.exe!Variant::clear() Line 257	C++
[Inlineframe] godot.windows.opt.tools.64.exe!Variant::{dtor}() Line 669	C++
[Inlineframe] godot.windows.opt.tools.64.exe!memdelete_allocator(Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::Element *) Line127	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 487	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 486	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 486	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 486	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 486	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 486	C++
godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::_cleanup_tree(Map<StringName,VariantComparator<StringName>,DefaultAllocator>::Element * p_element) Line 486	C++
[Inlineframe] godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::clear() Line 647	C++
[Inlineframe] godot.windows.opt.tools.64.exe!Map<StringName,Variant,Comparator<StringName>,DefaultAllocator>::{dtor}() Line 664	C++
godot.windows.opt.tools.64.exe!RendererStorageRD::Material::`scalar deleting destructor'(unsigned int)	C++
godot.windows.opt.tools.64.exe!RendererStorageRD::free(RID p_rid) Line 8614	C++
godot.windows.opt.tools.64.exe!RenderingServerDefault::_free(RID p_rid) Line 68	C++
[Inlineframe] godot.windows.opt.tools.64.exe!CommandQueueMT::flush_one(bool) Line 461	C++
godot.windows.opt.tools.64.exe!CommandQueueMT::flush_all() Line 509	C++
[Inlineframe] godot.windows.opt.tools.64.exe!CommandQueueMT::flush_if_pending() Line 503	C++
godot.windows.opt.tools.64.exe!RenderingServerDefault::canvas_item_clear(RID p1) Line 816	C++
godot.windows.opt.tools.64.exe!CanvasItem::_update_callback() Line 420	C++
[Inlineframe] godot.windows.opt.tools.64.exe!call_with_variant_args_helper(WebSocketServer *) Line 209	C++
[Inlineframe] godot.windows.opt.tools.64.exe!call_with_variant_args_dv(WebSocketServer *) Line 356	C++
godot.windows.opt.tools.64.exe!MethodBindT<WebSocketServer>::call(Object * p_object, const Variant * * p_args, int p_arg_count, Callable::CallError& r_error) Line 286	C++
godot.windows.opt.tools.64.exe!Object::call(const StringName & p_method, const Variant * * p_args, int p_argcount, Callable::CallError & r_error)Line 784	C++
godot.windows.opt.tools.64.exe!Callable::call(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError &r_call_error) Line 62	C++
godot.windows.opt.tools.64.exe!MessageQueue::_call_function(const Callable & p_callable, const Variant * p_args, int p_argcount, bool p_show_error)Line 259	C++
godot.windows.opt.tools.64.exe!MessageQueue::flush() Line 321	C++
godot.windows.opt.tools.64.exe!SceneTree::physics_process(float p_time) Line 415	C++
godot.windows.opt.tools.64.exe!Main::iteration() Line 2463	C++
godot.windows.opt.tools.64.exe!OS_Windows::run() Line 622	C++
godot.windows.opt.tools.64.exe!widechar_main(int argc, wchar_t * * argv) Line 163	C++
godot.windows.opt.tools.64.exe!_main() Line 187	C++
godot.windows.opt.tools.64.exe!main(int argc, char * * argv) Line 199	C++
[Inlineframe] godot.windows.opt.tools.64.exe!invoke_main() Line 78	C++
godot.windows.opt.tools.64.exe!__scrt_common_main_seh() Line 288	C++
kernel32.dll!00007ff80dc87034()	Unbekannt
ntdll.dll!00007ff80dea2651()	Unbekannt

The stack trace may vary in detail, but the loop taken in the RenderingServer remains (free -> Object::delete -> flush -> free -> deadlock).
Digging deeper, I tried to shrink the project (I was porting 3 gb big game) and found the causing root: preload. If you uncomment the line in Clue.gd you can import the project just fine.

Steps to reproduce:

  1. Open MRP with debugger
  2. Pause execution once Godot hangs
  3. Comment line 5 in Clue.gd and retry
  4. Uncomment line 5 in Clue.gd and replace ClueFound.tscn with spoiler below
ClueFound.tscn (4.)
[gd_scene load_steps=8 format=2]

[sub_resource type="Gradient" id=2]
offsets = PackedFloat32Array( 0, 0.766467, 1 )
colors = PackedColorArray( 0.0776427, 0.413086, 0.0322723, 1, 0.234318, 0.512695, 0.263134, 1, 0.498241, 0.647461, 0.554199, 0 )

[sub_resource type="GradientTexture" id=3]
;gradient = SubResource( 2 )

[sub_resource type="ParticlesMaterial" id=4]
direction = Vector3( 0, 1, 0 )
spread = 90.0
gravity = Vector3( 0, -0.4, 0 )
initial_velocity = 2.0
radial_accel = 0.5
tangential_accel = 1.0
;color_ramp = SubResource( 3 )

[sub_resource type="StandardMaterial3D" id=5]
transparency = 1
vertex_color_use_as_albedo = true
emission_enabled = true
emission = Color( 1, 1, 1, 1 )
emission_energy = 2.0
emission_operator = 1

[sub_resource type="BoxMesh" id=6]
;material = SubResource( 5 )
size = Vector3( 0.1, 0.1, 0.1 )

[node name="AudioStreamPlayer3D" type="AudioStreamPlayer3D"]

[node name="Particles" type="GPUParticles3D" parent="."]
emitting = false
amount = 1000
lifetime = 3.0
one_shot = true
explosiveness = 1.0
visibility_aabb = AABB( -8.69993, -2.03041, -8.73061, 17.4143, 8.54483, 17.4447 )
;process_material = SubResource( 4 )
;draw_pass_1 = SubResource( 6 )
script = null

ClueFound (1-3)
[gd_scene load_steps=8 format=2]

[sub_resource type="Gradient" id=2]
offsets = PackedFloat32Array( 0, 0.766467, 1 )
colors = PackedColorArray( 0.0776427, 0.413086, 0.0322723, 1, 0.234318, 0.512695, 0.263134, 1, 0.498241, 0.647461, 0.554199, 0 )

[sub_resource type="GradientTexture" id=3]
gradient = SubResource( 2 )

[sub_resource type="ParticlesMaterial" id=4]
direction = Vector3( 0, 1, 0 )
spread = 90.0
gravity = Vector3( 0, -0.4, 0 )
initial_velocity = 2.0
radial_accel = 0.5
tangential_accel = 1.0
color_ramp = SubResource( 3 )

[sub_resource type="StandardMaterial3D" id=5]
transparency = 1
vertex_color_use_as_albedo = true
emission_enabled = true
emission = Color( 1, 1, 1, 1 )
emission_energy = 2.0
emission_operator = 1

[sub_resource type="BoxMesh" id=6]
material = SubResource( 5 )
size = Vector3( 0.1, 0.1, 0.1 )

[node name="AudioStreamPlayer3D" type="AudioStreamPlayer3D"]

[node name="Particles" type="GPUParticles3D" parent="."]
emitting = false
amount = 1000
lifetime = 3.0
one_shot = true
explosiveness = 1.0
visibility_aabb = AABB( -8.69993, -2.03041, -8.73061, 17.4143, 8.54483, 17.4447 )
process_material = SubResource( 4 )
draw_pass_1 = SubResource( 6 )
script = null

Minimal reproduction project:
Free Deadlock.zip

@HaSa1002
Copy link
Contributor Author

HaSa1002 commented Jun 9, 2021

regression caused in/by: 8b19ffd (PR: #45852)

@HaSa1002
Copy link
Contributor Author

I changed all preloads to load and now get an crash in CommandQueueMT::_flush() on line 373 (cmd->call) instead. This may be related, but unrelated (it is happening again in a texture destructor)

@HaSa1002
Copy link
Contributor Author

Did another test in a debug build and the issue is indeed the same.

@akien-mga
Copy link
Member

I think this might be fixed by #50193, can you confirm?

@HaSa1002
Copy link
Contributor Author

HaSa1002 commented Jul 7, 2021

Yes it is fixed

@akien-mga
Copy link
Member

Fixed by #50193.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants