[shell] stdin_write blocks the main thread while the child isn't reading stdin

Aperta
#3,748 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
52/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
rust
Ambito
backend, cli

Direzione di ricerca

Start by reading the stdin_write command and the shell child management code that protects shell.children with a lock; the issue does not name file paths or tests. Compare the async kill change in issue #3351 and trace how writes from JavaScript preserve order. Done means large writes no longer block the main thread, while child cleanup and other commands can proceed and writes remain ordered; the issue leaves the design open.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

plugin: shell type: bug
Describe the bug

stdin_write is a sync command, so it runs on the main thread, and it does a blocking write_all into the child's stdin pipe. If the data is bigger than the pipe buffer and the child isn't reading its stdin at that moment, the main thread waits until the child reads. The whole window freezes for that time, and if the child never reads stdin it stays frozen.

It also holds shell.children.lock() during the write, so from reading the code every other shell command (spawn, kill, writes to other children) and the Terminated cleanup wait on that lock too. I only measured the main thread part.

#3351 made kill async for the same main thread reason, stdin_write is still sync.

Reproduction

Spawn sh -c 'sleep 6; cat >/dev/null' from JS, call child.write() (plugin:shell|stdin_write) with 1 MiB, then 100 ms later call any other sync command and time it.

macOS 26.5.1, Tauri 2.12.5, tauri-plugin-shell 2.6.0:

32 KiB write: the other command answers in 1 ms

1 MiB write, child reads after 6 s: the other command answers after 5918 ms and 5916 ms (2 runs)

1 MiB write, child reads after 20 s: 19918 ms

A stack sample of the 20 s run, taken while it was stuck, has the main thread in tauri_plugin_shell::commands::stdin_write > std::io::Write::write_all > write in 2605 of 2605 samples.

I can put the probe app in a repo if that helps.

Expected behavior

Writing to a child's stdin shouldn't block the main thread, at least not for longer than it takes to copy the data.

Full tauri info output
[✘] Environment
    - OS: Mac OS 26.5.1 arm64 (X64)
    ✔ Xcode Command Line Tools: installed
    ✘ Xcode: not installed!
    ✔ rustc: 1.95.0 (59807616e 2026-04-14)
    ✔ cargo: 1.95.0 (f2d3ce0bd 2026-03-21)
    ✔ rustup: 1.29.1 (d95a37b6a 2026-08-13)
    ✔ Rust toolchain: stable-aarch64-apple-darwin (default)
    - node: 26.8.1
    - pnpm: 12.11.2
    - yarn: 1.22.22
    - npm: 11.19.0
    - bun: 1.4.2
    - deno: deno 2.9.7

[-] Packages
    - tauri 🦀: 2.12.5
    - tauri-build 🦀: 2.7.4
    - wry 🦀: 0.57.1
    - tao 🦀: 0.37.2

[-] Plugins
    - tauri-plugin-shell 🦀: 2.6.0

[-] App
    - build-type: build
    - CSP: unset
    - frontendDist: dist
Additional context

I'd like to send a fix but the shape needs a decision, which is why this is an issue first. Just making the command async moves the wait off the main thread, but the write would still hold the children lock, so a kill meant to get out of the stuck write would wait behind it. And writes from JS would need to keep their order, which they get for free today because they all run on the main thread.

One way: make it async, take what's needed to write out of children under the lock (or give each child its own writer task with a queue, so order is kept), and do the blocking write in spawn_blocking. Happy to do whichever you prefer.

Lingua principale
Rust
Stelle
1.8k
Fork
637
Merge medio
5g 3h
PR unite (30g)
36

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di tauri-apps/plugins-workspace

Tutte le issue di tauri-apps/plugins-workspace

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.