EndEventMismatch error when asynchronously reading to end in loop
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 35/100
Direzione di ricerca
Start by reading the reproducer in the issue and tracing how read_event_into_async() and read_to_end_into_async() handle buffered input across a timeout. Reproduce the second-iteration failure with the supplied XmlReader; done means the same loop reads both <tag></tag> messages without EndEventMismatch.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
I've been getting an unusual EndEventMismatch error when reading from a TCP (TLS) socket in a loop.
The error message is "Expecting </<tag> found </tag>" EndEventMismatch { expected: "<tag", found: "tag" }.
I managed to write a small(ish) self-contained reproducible example:
main.rs
use std::time::Duration;
use quick_xml::events::Event as XmlEvent;
use tokio::io::{AsyncRead, BufReader};
struct XmlReader {
next_message_ready: bool,
}
impl XmlReader {
fn new() -> Self {
Self {
next_message_ready: false,
}
}
}
impl AsyncRead for XmlReader {
fn poll_read(
mut self: std::pin::Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> std::task::Poll<std::io::Result<()>> {
if !self.next_message_ready {
return std::task::Poll::Pending;
}
let response = "<tag></tag>";
buf.put_slice(response.as_bytes());
self.next_message_ready = false;
std::task::Poll::Ready(Ok(()))
}
}
struct XmlConsumer {
reader: quick_xml::Reader<BufReader<XmlReader>>,
}
impl XmlConsumer {
pub fn new() -> XmlConsumer {
let reader = XmlReader::new();
let reader = BufReader::new(reader);
let reader = quick_xml::Reader::from_reader(reader);
Self { reader }
}
pub fn set_next_message_ready(&mut self) {
self.reader.get_mut().get_mut().next_message_ready = true;
}
pub async fn recv_xml(&mut self) {
// read start event
let mut buf = Vec::new();
let start_event = self.reader.read_event_into_async(&mut buf).await.unwrap();
println!(
"\n\nstart_event={:?} buffer position={}",
start_event,
self.reader.buffer_position()
);
let bytes_start = match start_event {
XmlEvent::Start(e) => e,
_ => panic!("Expected Start event"),
};
// read until corresponding end event
let mut buf = Vec::new();
let span = self
.reader
.read_to_end_into_async(bytes_start.name(), &mut buf)
.await
.unwrap(); // <- panics here
println!(
"read to end, span={:?} buffer position={}",
span,
self.reader.buffer_position()
);
}
}
#[tokio::main]
async fn main() {
let mut xml_consumer = XmlConsumer::new();
loop {
xml_consumer.set_next_message_ready();
loop {
let xml_event_fut = xml_consumer.recv_xml();
let xml_event_fut = tokio::time::timeout(Duration::from_millis(1), xml_event_fut);
let r = xml_event_fut.await;
if r.is_err() {
println!("Timeout");
break;
}
}
}
}
This script sets up a mock object called XmlReader that implements AsyncRead. It is supposed to represent a TCP echo server of sorts, that responds with "<tag></tag>" whenever next_message_ready is set to true. It is then wrapped in a BufReader and fed to quick_xml.
The read_event_into_async() and read_to_end_into_async() methods are called one after the other, in a loop. On the second iteration on the loop, the quick_xml reader seems to read <<tag> instead of <tag> somehow, causing an error when it tries to read the matching closing tag.
Here are the logs generated by the code above:
start_event=Start(BytesStart { buf: Borrowed("tag"), name_len: 3 }) buffer position=5
read to end, span=5..5 buffer position=11
Timeout
start_event=Start(BytesStart { buf: Borrowed("<tag"), name_len: 4 }) buffer position=16
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: EndEventMismatch { expected: "<tag", found: "tag" }', src\main.rs:73:14
- Lingua principale
- Rust
- Stelle
- 1.6k
- Fork
- 299
- Merge medio
- 2g 4h
- PR unite (30g)
- 9
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di tafia/quick-xml
-
Parser accepts an empty element or attribute nameForse già presa @ychampion l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
DecodingReader::set_encoding panics when the XML declaration is longer than 64 bytesForse già presa @emschwartz l’ha presa 4 giorni fa. Apertabug encoding
Difficoltà 4/5 3-5 giorni Idoneità per principianti 30/100
tafia/quick-xml#1040 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
encoding optimization
Difficoltà 4/5 3-5 giorni Idoneità per principianti 55/100
tafia/quick-xml#1039 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
optimization question
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 4/5 1-2 giorni Idoneità per principianti 53/100
tafia/quick-xml#1035 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di tafia/quick-xml
Issue simili
-
[Bug]: opencode_go chat route drops reasoning_effort (even 'none'), while the same endpoint honors it via custom_llm_provider=openaiForse già presa @arvindkumar-ship-it l’ha presa oggi. Apertallm translation
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
BerriAI/litellm#51871 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
comp-formats
Difficoltà 2/5 Mezza giornata Idoneità per principianti 64/100
ClickHouse/ClickHouse#131694 ·
I maintainer di solito rispondono entro 1 giorno
-
cli: `execCargoMetadata` decodes stdout per chunk, corrupting non-ASCII paths across pipe boundariesAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
I maintainer di solito rispondono entro 1 giorno
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
C-Bug S-Needs-Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
bevyengine/bevy#26558 ·
I maintainer di solito rispondono entro 2 giorni