Skip to content

Commit 9223622

Browse files
committed
Fix but-server claude websocket events
Move reading of the child process stdout into a dedicated blocking thread and forward lines through an unbounded tokio mpsc channel to the async task. Replace the previous direct async BufReader lines() loop with a blocking std::thread::spawn that calls BufReader::lines() and sends each Ok line over tx; the async side now awaits rx.recv(). This prevents blocking the tokio runtime on stdio reads, avoids calling blocking I/O in async context, and preserves line-by-line delivery for downstream JSON parsing and handling.
1 parent a771d39 commit 9223622

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

crates/but-claude/src/bridge.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -608,11 +608,21 @@ fn spawn_response_streaming(
608608
stack_id: StackId,
609609
) -> tokio::task::JoinHandle<()> {
610610
tokio::spawn(async move {
611-
let reader = BufReader::new(read_stdout);
611+
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<String>();
612+
613+
// Spawn a blocking task to read lines from the pipe
614+
std::thread::spawn(move || {
615+
let reader = BufReader::new(read_stdout);
616+
for line in reader.lines().map_while(Result::ok) {
617+
if tx.send(line).is_err() {
618+
break;
619+
}
620+
}
621+
});
622+
612623
let mut first = true;
613-
for line in reader.lines() {
624+
while let Some(line) = rx.recv().await {
614625
let mut ctx = ctx.lock().await;
615-
let line = line.unwrap();
616626
let parsed_event: serde_json::Value = serde_json::from_str(&line).unwrap();
617627

618628
if first {

0 commit comments

Comments
 (0)