fix input to check pty child (#6553)

* fix input to check pty child

* Auto-format: cargo fmt --all

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jeong, YunWonandgithub-actions[bot] authored and GitHub committed 2025-12-28 09:08:03 +09:00
1 parent 9b2ad34a08
commit ce00640b22
2 files changed
+30 -7

No files matched your search

+6 -3
View File
@@ -70,11 +70,14 @@ pub fn file_readline(obj: &PyObject, size: Option<usize>, vm: &VirtualMachine) -
};
let ret = match_class!(match ret {
s @ PyStr => {
let s_val = s.as_str();
if s_val.is_empty() {
// Use as_wtf8() to handle strings with surrogates (e.g., surrogateescape)
let s_wtf8 = s.as_wtf8();
if s_wtf8.is_empty() {
return Err(eof_err());
}
if let Some(no_nl) = s_val.strip_suffix('\n') {
// '\n' is ASCII, so we can check bytes directly
if s_wtf8.as_bytes().last() == Some(&b'\n') {
let no_nl = &s_wtf8[..s_wtf8.len() - 1];
vm.ctx.new_str(no_nl).into()
} else {
s.into()
+24 -4
View File
@@ -7,8 +7,6 @@ pub use builtins::{ascii, print, reversed};
#[pymodule]
mod builtins {
use std::io::IsTerminal;
use crate::{
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
builtins::{
@@ -464,6 +462,8 @@ mod builtins {
#[pyfunction]
fn input(prompt: OptionalArg<PyStrRef>, vm: &VirtualMachine) -> PyResult {
use std::io::IsTerminal;
let stdin = sys::get_stdin(vm)?;
let stdout = sys::get_stdout(vm)?;
let stderr = sys::get_stderr(vm)?;
@@ -476,8 +476,13 @@ mod builtins {
.is_ok_and(|fd| fd == expected)
};
// everything is normal, we can just rely on rustyline to use stdin/stdout
if fd_matches(&stdin, 0) && fd_matches(&stdout, 1) && std::io::stdin().is_terminal() {
// Check if we should use rustyline (interactive terminal, not PTY child)
let use_rustyline = fd_matches(&stdin, 0)
&& fd_matches(&stdout, 1)
&& std::io::stdin().is_terminal()
&& !is_pty_child();
if use_rustyline {
let prompt = prompt.as_ref().map_or("", |s| s.as_str());
let mut readline = Readline::new(());
match readline.readline(prompt) {
@@ -502,6 +507,21 @@ mod builtins {
}
}
/// Check if we're running in a PTY child process (e.g., after pty.fork()).
/// pty.fork() calls setsid(), making the child a session leader.
/// In this case, rustyline may hang because it uses raw mode.
#[cfg(unix)]
fn is_pty_child() -> bool {
use nix::unistd::{getpid, getsid};
// If this process is a session leader, we're likely in a PTY child
getsid(None) == Ok(getpid())
}
#[cfg(not(unix))]
fn is_pty_child() -> bool {
false
}
#[pyfunction]
fn isinstance(obj: PyObjectRef, typ: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
obj.is_instance(&typ, vm)