Awesome Reviewers

When concurrency touches shared state, ensure (a) mutexes don’t guard blocking I/O, (b) slow/blocking operations run on dedicated worker threads, (c) state cleanup is race-safe, and (d) any external probe has a timeout and non-fatal fallback.

Practical rules 1) Don’t hold locks across blocking calls

2) Offload long/contended I/O to worker threads

3) Make cleanup/removal race-safe

4) Never block critical threads on external probes; use timeouts

5) Guard lifecycle concurrency at the app level

Illustrative pattern (writer worker + enqueue)

use std::{sync::{Arc, Mutex, mpsc}, thread};

struct Session { tx: mpsc::Sender<Vec<u8>> }

fn start_session(shared: Arc<Mutex<std::collections::HashMap<String, Session>>>, id: String) {
    let (tx, rx) = mpsc::channel::<Vec<u8>>();

    // Writer worker: only this thread performs blocking writes.
    thread::spawn(move || {
        while let Ok(bytes) = rx.recv() {
            // blocking I/O here, not under shared locks
            // pty_writer.write_all(&bytes).ok();
        }
        // tx dropped => worker ends
    });

    shared.lock().unwrap().insert(id, Session { tx });
}

fn terminal_write(shared: &Arc<Mutex<std::collections::HashMap<String, Session>>>, id: &str, data: Vec<u8>) {
    // Lock only long enough to grab the sender.
    let tx = { shared.lock().unwrap().get(id).unwrap().tx.clone() };
    let _ = tx.send(data); // enqueue; never block here
}

Use this standard to prevent UI/IPC stalls, avoid lock-induced deadlocks/perf cliffs, and eliminate stale-thread state races.