script: Fix deadlock in async html parser (#42930)

When the async parser thread finds a `<meta charset>` tag then it asks
the main thread whether parsing should restart. The main thread wasn't
responding, so the parser got stuck.


Part of https://github.com/servo/servo/issues/37418
Testing: This change adds a test

---------

Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
Simon Wülker
2026-03-02 13:15:41 +01:00
committed by GitHub
parent 71974ea830
commit e033588b30
4 changed files with 32 additions and 8 deletions

View File

@@ -154,7 +154,10 @@ enum FromParserThreadMsg {
script: ParseNode,
updated_input: VecDeque<SendTendril<UTF8>>,
},
EncodingIndicator(SendTendril<UTF8>),
EncodingIndicator {
encoding: SendTendril<UTF8>,
updated_input: VecDeque<SendTendril<UTF8>>,
},
/// Sent to main thread to signify that the parser thread's end method has returned.
End,
ProcessOperation(ParseOperation),
@@ -338,7 +341,15 @@ impl Tokenizer {
let script = self.get_node(&script.id);
return TokenizerResult::Script(DomRoot::from_ref(script.downcast().unwrap()));
},
FromParserThreadMsg::EncodingIndicator(_) => continue,
FromParserThreadMsg::EncodingIndicator { updated_input, .. } => {
// We don't handle encoding indicators yet, so just tell the
// parser thread to continue.
self.to_parser_thread_sender
.send(ToParserThreadMsg::Feed {
input: updated_input,
})
.unwrap();
},
_ => unreachable!(),
};
}
@@ -363,11 +374,8 @@ impl Tokenizer {
self.process_operation(parse_op, cx);
},
FromParserThreadMsg::TokenizerResultDone { updated_input: _ } |
FromParserThreadMsg::TokenizerResultScript {
script: _,
updated_input: _,
} |
FromParserThreadMsg::EncodingIndicator(_) => continue,
FromParserThreadMsg::TokenizerResultScript { .. } |
FromParserThreadMsg::EncodingIndicator { .. } => continue,
FromParserThreadMsg::End => return,
};
}
@@ -692,7 +700,10 @@ fn run(
updated_input,
},
TokenizerResult::EncodingIndicator(encoding) => {
FromParserThreadMsg::EncodingIndicator(SendTendril::from(encoding))
FromParserThreadMsg::EncodingIndicator {
encoding: SendTendril::from(encoding),
updated_input,
}
},
};
sender.send(res).unwrap();

View File

@@ -2,6 +2,13 @@
"items": {
"crashtest": {
"mozilla": {
"async-html-meta-charset-crash.html": [
"8743acb152daa256af34bc938f688561abd313c1",
[
null,
{}
]
],
"audioContext_createMediaElementSource-crash.html": [
"e70316d3e6d880d8ec9600ff157e81f6047871a4",
[

View File

@@ -0,0 +1,2 @@
[async-html-meta-charset-crash.html]
prefs: ["dom_servoparser_async_html_tokenizer_enabled:true"]

View File

@@ -0,0 +1,4 @@
<!DOCTYPE html>
<head>
<meta charset="utf-8">
</head>