Skip to content

Commit 640357b

Browse files
committed
fix: only serialize PTY spawn on musl, not entire lifetime
The previous fix held the mutex for the Terminal's entire lifetime, which serialized all PTY tests within a binary. With 8 tests having 5-second timeouts, later tests would time out waiting for the lock (4/10 CI runs failed with exit code 101). The SIGSEGV occurs in musl's sysconf/fcntl during openpty + fork/exec, not during normal FD I/O on already-open PTYs. Restrict the lock to just the spawn section so tests can run concurrently after creation. https://claude.ai/code/session_011H8UR3gS6hoyQAf2x7Dfw8
1 parent 73de573 commit 640357b

File tree

1 file changed

+5
-15
lines changed

1 file changed

+5
-15
lines changed

crates/pty_terminal/src/terminal.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,6 @@ pub struct Terminal {
5151
pub pty_reader: PtyReader,
5252
pub pty_writer: PtyWriter,
5353
pub child_handle: ChildHandle,
54-
55-
/// On musl libc, concurrent PTY operations (openpty, fork/exec, FD I/O)
56-
/// trigger SIGSEGV/SIGBUS in musl internals. This guard serializes the
57-
/// entire PTY lifecycle so only one Terminal is active at a time.
58-
#[cfg(target_env = "musl")]
59-
_pty_guard: std::sync::MutexGuard<'static, ()>,
6054
}
6155

6256
struct Vt100Callbacks {
@@ -262,15 +256,13 @@ impl Terminal {
262256
///
263257
/// Panics if the writer lock is poisoned when the background thread closes it.
264258
pub fn spawn(size: ScreenSize, cmd: CommandBuilder) -> anyhow::Result<Self> {
265-
// On musl libc (Alpine Linux), concurrent PTY operations (openpty,
266-
// fork/exec, FD I/O) trigger SIGSEGV/SIGBUS in musl internals.
267-
// Hold the lock for the Terminal's entire lifetime so only one PTY
268-
// is active at a time.
269-
// See: https://github.com/voidzero-dev/vite-task/pull/278
259+
// On musl libc (Alpine Linux), concurrent openpty + fork/exec
260+
// operations trigger SIGSEGV/SIGBUS in musl internals (observed
261+
// in sysconf, fcntl). Serialize PTY creation and child spawning.
270262
#[cfg(target_env = "musl")]
271-
static PTY_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
263+
static SPAWN_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
272264
#[cfg(target_env = "musl")]
273-
let pty_guard = PTY_LOCK.lock().unwrap_or_else(|e| e.into_inner());
265+
let _spawn_guard = SPAWN_LOCK.lock().unwrap_or_else(|e| e.into_inner());
274266

275267
let pty_pair = portable_pty::native_pty_system().openpty(portable_pty::PtySize {
276268
rows: size.rows,
@@ -322,8 +314,6 @@ impl Terminal {
322314
pty_reader: PtyReader { reader, parser: Arc::clone(&parser) },
323315
pty_writer: PtyWriter { writer, parser, master },
324316
child_handle: ChildHandle { child_killer, exit_status },
325-
#[cfg(target_env = "musl")]
326-
_pty_guard: pty_guard,
327317
})
328318
}
329319
}

0 commit comments

Comments
 (0)