mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
fix(pty): treat background jobs as non-interactive to avoid SIGTTOU stop (#324)
* fix(pty): treat background jobs as non-interactive to avoid SIGTTOU stop IsInteractiveTerminal only checked that stdin/stdout are TTYs. A background job (pmg npm run test &) still has the TTY on stdin/stdout, so pmg picked PTY mode and called tcsetattr to enter raw mode. Changing terminal modes from a background process group makes the kernel stop the process with SIGTTOU, leaving the job hanging in Stopped state. Check that the process group is the terminal's foreground process group (tcgetpgrp == getpgrp) before treating the terminal as interactive, so background jobs fall through to direct execution. Fixes #322 https://claude.ai/code/session_01PBBo5CKkzg68MMGrgCTQcY * test(pty): fail on output copy timeout to avoid racy buffer read Reading the output buffer after a silent select timeout races with the io.Copy goroutine still writing to it. Fail the test on timeout instead. Also fix a grammar nit in the IsInteractiveTerminal doc comment. https://claude.ai/code/session_01PBBo5CKkzg68MMGrgCTQcY --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -42,9 +42,11 @@ type InteractiveSession interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// IsInteractiveTerminal returns true if stdin is a real terminal (TTY).
|
||||
// Returns false in CI environments (when the "CI" env var set to "true"),
|
||||
// when input or output is piped, or in non-interactive shells.
|
||||
// IsInteractiveTerminal returns true if stdin is a real terminal (TTY) and
|
||||
// the process can safely drive it. Returns false in CI environments (when the
|
||||
// "CI" env var is set to "true"), when input or output is piped, in
|
||||
// non-interactive shells, or when running as a background job (where putting
|
||||
// the terminal into raw mode would stop the process with SIGTTOU).
|
||||
func IsInteractiveTerminal() bool {
|
||||
if ci := os.Getenv("CI"); ci != "" && strings.ToLower(ci) == "true" {
|
||||
return false
|
||||
@@ -58,7 +60,7 @@ func IsInteractiveTerminal() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
return isForegroundProcess(os.Stdin.Fd())
|
||||
}
|
||||
|
||||
var _ InteractiveSession = &session{}
|
||||
|
||||
Reference in New Issue
Block a user