EmbarkStudios / EmbarkStudios/puffin
puffin_egui deadlock if new_frame is called from another thread
- Dominant language
- Rust
- Stars
- 1.7k
- Forks
- 111
- Avg merge
- 2h 50m
- Merged PRs (30d)
- 1
Description
I'm running into a deadlock in `puffin_egui` if `new_frame()` is called from a thread other than the UI thread.
I built a sampling profiler that runs in a single thread, manually creates `ThreadProfiler` instances for all threads running in the process, and samples their stack traces at intervals, so I'm calling `new_frame` from that thread rather than my UI thread.
Here puffin takes the `GlobalFrameView` lock and holds it across the UI function call:
https://github.com/EmbarkStudios/puffin/blob/0dd10b2d4d67416fe340716b7bd0fa0ab4138491/puffin_egui/src/lib.rs#L117-L130
The profiler ui call itself contains profiling calls, which calls `ThreadProfiler::end_scope` internally, which tries to take the `GlobalProfiler` lock. So you have a nested `GlobalFrameView` lock -> `GlobalProfiler` lock acquisition in the UI.
`GlobalProfiler::lock().new_frame()` has the `GlobalProfiler` locked and calls the sink function here, which tries to lock the `GlobalFrameView`: https://github.com/EmbarkStudios/puffin/blob/0dd10b2d4d67416fe340716b7bd0fa0ab4138491/puffin/src/profile_view.rs#L259
This mismatched lock order triggers a deadlock.
Contributor guide
Assessment
This issue has not been assessed yet.