You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
MySQL: a cancelled prepare leaves its response on the stream #4427
#563 covers cancellation in the middle of a packet read; this reproduces with responses too small for that window.
Description
prepare_statement reads the COM_STMT_PREPARE response inline and records nothing in waiting, while run has already queued Waiting::Result. A prepare cancelled before its response is read leaves stmt-prepare-ok and the definition packets on the stream. The drain takes stmt-prepare-ok for the queued result, and the next command reads a column definition (0x03) as its reply. A failed parameter-count check leaves the same queued entry without any cancellation, and the next command hangs.
Reproduction steps
// sqlx = { version = "=0.9.0", default-features = false, features = ["mysql", "runtime-tokio"] }// tokio = { version = "1", features = ["macros", "rt"] }use sqlx::{Connection,MySqlConnection};#[tokio::main(flavor = "current_thread")]asyncfnmain() -> Result<(),Box<dyn std::error::Error>>{letmut conn = MySqlConnection::connect(&std::env::var("DATABASE_URL")?).await?;for i in0..100{// Poll the query once, which sends COM_STMT_PREPARE, then drop it.
tokio::select! {
biased;
r = sqlx::query("SELECT ? AS a, 'b' AS b, 'c' AS c, 'd' AS d").bind(1i64).fetch_all(&mut conn) => { r?;}
_ = std::future::ready(()) => {}}
conn.ping().await.map_err(|e| format!("iteration {i}: {e}"))?;}println!("ok");Ok(())}
On 0.9.0 and on main (b54008a) the ping fails at iteration 0 in 10 of 10 runs: expected 0x00 or 0xfe (OK_Packet) but found 0x03. Without a cancellation, sqlx::query("SELECT ?").execute(&mut conn) fails its parameter-count check, and the next conn.ping() hangs (3 of 3 runs on each).
Activity