Thanks to visit codestin.com
Credit goes to github.com

Skip to content

devtools: Panic with ActorRegistry already mutably borrowed #45055

@eerii

Description

@eerii

Describe the bug:
The issue here is that we are using an AtomicRefCell to control access to the ActorRegistry via a shared reference. When we try to read or write it when we are already writing it (i.e. registering an actor inside another actor register function), it panics.

There are a few things to solve here. First, the actor dependency graph we have at the moment is convoluted. The PR (peding) for fixing the inspector after navigation improves things, but it doesn't fix all cases. There are loops in actor dependencies for registration and tricky cases.

The second part is that ActorRegistry::register both creates an actor name, adds the actor to the registry, and returns the name. All of this must be done while holding a mutable lock. This is an issue for dependencies, since sometimes we are passing the current actor name to other new ones during registration, and then saving the other ones in the current actor. So using names as a handle makes this problematic situation easy to do.

Finally, we should probably move to something like RwLock to avoid panics, but only after we are sure that the registry is structured in a way that doesn't allow deadlocks.

I have been working on a series of patches to fix this issue, I'll be sending them incrementally. They are not complex patches, but because they change all the actors, the line count can get big quickly.

To Reproduce:
Difficult to reliably reproduce, as it is a racing condition. I have triggered this a few times last weeks for different places (mainly NodeActor and NetworkEventActor. It usually happens when loading very big pages with many actors.

Platform:
All platforms.

Stack trace:

[2026-05-21T10:41:11Z DEBUG devtools::actor] registering NodeActor223 (90f38d9fe8fd4042bbcf2e438a32281a)
already mutably borrowed (thread Devtools, at /home/eri/Code/igalia/servo/home/.local/share/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/atomic_refcell-0.1.14/src/lib.rs:158)
   0: servoshell::backtrace::print
             at /home/eri/Code/igalia/servo/servo-main/ports/servoshell/backtrace.rs:18:5
   1: servoshell::panic_hook::panic_hook
             at /home/eri/Code/igalia/servo/servo-main/ports/servoshell/panic_hook.rs:40:17
   2: core::ops::function::Fn::call
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:79:5
   3: <alloc::boxed::Box<dyn for<'a, 'b> core::ops::function::Fn<(&'a std::panic::PanicHookInfo<'b>,), Output = ()> + core::marker::Sync + core::marker::Send> as core::ops::function::Fn<(&std::panic::PanicHookInfo,)>>::call
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/boxed.rs:2254:9
      std::panicking::panic_with_hook
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:833:13
   4: std::panicking::panic_handler::{closure#0}
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:698:13
   5: std::sys::backtrace::__rust_end_short_backtrace::<std::panicking::panic_handler::{closure#0}, !>
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/backtrace.rs:182:18
   6: __rustc::rust_begin_unwind
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/panicking.rs:689:5
   7: core::panicking::panic_fmt
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/core/src/panicking.rs:80:14
   8: core::panicking::panic_display
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panicking.rs:259:5
   9: atomic_refcell::AtomicRefCell<T>::borrow_mut
             at /home/eri/Code/igalia/servo/home/.local/share/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/atomic_refcell-0.1.14/src/lib.rs:158:23
  10: devtools::actor::ActorRegistry::register
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/actor.rs:178:14
  11: devtools::actors::network_event::NetworkEventActor::register
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/actors/network_event.rs:546:18
  12: devtools::DevtoolsInstance::create_network_event_actor
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/lib.rs:736:13
  13: devtools::DevtoolsInstance::handle_network_event
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/lib.rs:719:26
  14: devtools::DevtoolsInstance::run
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/lib.rs:405:26
  15: devtools::start_server::{{closure}}::{{closure}}
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/lib.rs:136:38
  16: profile_traits::mem::ProfilerChan::run_with_memory_reporting
             at /home/eri/Code/igalia/servo/servo-main/components/shared/profile/mem.rs:143:9
  17: devtools::start_server::{{closure}}
             at /home/eri/Code/igalia/servo/servo-main/components/devtools/lib.rs:132:35
  18: std::sys::backtrace::__rust_begin_short_backtrace
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/backtrace.rs:166:18
  19: std::thread::lifecycle::spawn_unchecked::{{closure}}::{{closure}}
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/lifecycle.rs:91:13
  20: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:274:9
  21: std::panicking::catch_unwind::do_call
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:581:40
  22: __rust_try
  23: std::panicking::catch_unwind
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panicking.rs:544:19
      std::panic::catch_unwind
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/panic.rs:359:14
      std::thread::lifecycle::spawn_unchecked::{{closure}}
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/thread/lifecycle.rs:89:26
  24: core::ops::function::FnOnce::call_once{{vtable.shim}}
             at /home/eri/Code/igalia/servo/home/.local/share/rustup/toolchains/1.95.0-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
  25: <alloc::boxed::Box<dyn core::ops::function::FnOnce<(), Output = ()> + core::marker::Send> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/alloc/src/boxed.rs:2240:9
      <std::sys::thread::unix::Thread>::new::thread_start
             at /rustc/59807616e1fa2540724bfbac14d7976d7e4a3860/library/std/src/sys/thread/unix.rs:118:17
  26: <unknown>
  27: <unknown>

Metadata

Metadata

Assignees

Labels

A-devtoolsC-assignedThere is someone working on resolving the issueI-panicServo encounters a panic.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions