diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 51f7b6fbe05..3ad7a2e7edf 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -64,6 +64,34 @@ //! //! Since there is only one constellation, and its responsibilities include crash reporting, //! it is very important that it does not panic. +//! +//! It's also important that the constellation not deadlock. In particular, we need +//! to be careful that we don't introduce any cycles in the can-block-on relation. +//! Blocking is typically introduced by `receiver.recv()`, which blocks waiting for the +//! sender to send some data. Servo tries to achieve deadlock-freedom by using the following +//! can-block-on relation: +//! +//! * Layout can block on canvas +//! * Layout can block on font cache +//! * Layout can block on image cache +//! * Constellation can block on compositor +//! * Constellation can block on embedder +//! * Constellation can block on layout +//! * Script can block on anything (other than script) +//! * Blocking is transitive (if T1 can block on T2 and T2 can block on T3 then T1 can block on T3) +//! * Nothing can block on itself! +//! +//! There is a complexity intoduced by IPC channels, since they do not support +//! non-blocking send. This means that as well as `receiver.recv()` blocking, +//! `sender.send(data)` can also block when the IPC buffer is full. For this reason it is +//! very important that all IPC receivers where we depend on non-blocking send +//! use a router to route IPC messages to an mpsc channel. The reason why that solves +//! the problem is that under the hood, the router uses a dedicated thread to forward +//! messages, and: +//! +//! * Anything (other than a routing thread) can block on a routing thread +//! +//! See https://github.com/servo/servo/issues/14704 use backtrace::Backtrace; use bluetooth_traits::BluetoothRequest;