script: Unconditionally send exit message during pipeline shutdown (#36808)

If a `WebView` is dropped immediately after creating it, the exit
pipeline message can arrive to the `ScriptThread` before the `Document`
is created for the pipeline. If this happens, we should still send a
message to the `Constellation` informing it that the pipeline is closed,
otherwise it will never know that this has happened properly.

Testing: This change includes a new unit test.
Fixes: #36807.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Martin Robinson 2025-05-05 09:44:30 +02:00 committed by GitHub
parent 21df8b875b
commit 20f20a07f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 10 deletions

View file

@ -2813,8 +2813,6 @@ impl ScriptThread {
) {
debug!("{id}: Starting pipeline exit.");
self.closed_pipelines.borrow_mut().insert(id);
// Abort the parser, if any,
// to prevent any further incoming networking messages from being handled.
let document = self.documents.borrow_mut().remove(id);
@ -2835,12 +2833,6 @@ impl ScriptThread {
debug!("{id}: Shutting down layout");
document.window().layout_mut().exit_now();
debug!("{id}: Sending PipelineExited message to constellation");
self.senders
.pipeline_to_constellation_sender
.send((id, ScriptToConstellationMessage::PipelineExited))
.ok();
// Clear any active animations and unroot all of the associated DOM objects.
debug!("{id}: Clearing animations");
document.animations().clear();
@ -2863,6 +2855,15 @@ impl ScriptThread {
window.clear_js_runtime();
}
// Prevent any further work for this Pipeline.
self.closed_pipelines.borrow_mut().insert(id);
debug!("{id}: Sending PipelineExited message to constellation");
self.senders
.pipeline_to_constellation_sender
.send((id, ScriptToConstellationMessage::PipelineExited))
.ok();
debug!("{id}: Finished pipeline exit");
}

View file

@ -44,6 +44,18 @@ fn test_create_webview(servo_test: &ServoTest) -> Result<(), anyhow::Error> {
Ok(())
}
fn main() {
run_api_tests!(test_create_webview);
fn test_create_webview_and_immediately_drop_webview_before_shutdown(
servo_test: &ServoTest,
) -> Result<(), anyhow::Error> {
WebViewBuilder::new(servo_test.servo()).build();
Ok(())
}
fn main() {
run_api_tests!(
test_create_webview,
// This test needs to be last, as it tests creating and dropping
// a WebView right before shutdown.
test_create_webview_and_immediately_drop_webview_before_shutdown
);
}