fix read/1 on non-TTY stdin blocking until newline #3262
This commit is contained in:
@@ -23,7 +23,7 @@ use std::fmt::Debug;
|
|||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::{Cursor, ErrorKind, Read, Seek, SeekFrom, Write};
|
use std::io::{Cursor, ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write};
|
||||||
use std::mem::ManuallyDrop;
|
use std::mem::ManuallyDrop;
|
||||||
use std::net::{Shutdown, TcpStream};
|
use std::net::{Shutdown, TcpStream};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
@@ -657,10 +657,27 @@ impl Stream {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn stdin(arena: &mut Arena, add_history: bool) -> Stream {
|
pub fn stdin(arena: &mut Arena, add_history: bool) -> Stream {
|
||||||
Stream::Readline(arena_alloc!(
|
if std::io::stdin().is_terminal() {
|
||||||
StreamLayout::new(ReadlineStream::new("", add_history)),
|
Stream::Readline(arena_alloc!(
|
||||||
arena
|
StreamLayout::new(ReadlineStream::new("", add_history)),
|
||||||
))
|
arena
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::io::{FromRawFd, RawFd};
|
||||||
|
// dup fd 0 so the File can be owned (and closed later) without
|
||||||
|
// closing the real stdin.
|
||||||
|
let fd = unsafe { libc::dup(0 as RawFd) };
|
||||||
|
let file = unsafe { File::from_raw_fd(fd) };
|
||||||
|
return Stream::from_file_as_input(atom!("user_input"), file, arena);
|
||||||
|
}
|
||||||
|
#[allow(unreachable_code)]
|
||||||
|
Stream::Readline(arena_alloc!(
|
||||||
|
StreamLayout::new(ReadlineStream::new("", add_history)),
|
||||||
|
arena
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_tag(tag: ArenaHeaderTag, ptr: UntypedArenaPtr) -> Self {
|
pub fn from_tag(tag: ArenaHeaderTag, ptr: UntypedArenaPtr) -> Self {
|
||||||
|
|||||||
4
tests-pl/issue3262.pl
Normal file
4
tests-pl/issue3262.pl
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
:- initialization(main).
|
||||||
|
main :-
|
||||||
|
read(Term),
|
||||||
|
write(Term).
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::helper::load_module_test;
|
use crate::helper::load_module_test;
|
||||||
|
use crate::helper::load_module_test_with_input;
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::helper::load_module_test_with_tokio_runtime;
|
use crate::helper::load_module_test_with_tokio_runtime;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
@@ -148,6 +149,13 @@ fn issue_rename_file() {
|
|||||||
load_module_test("tests-pl/issue_rename_file.pl", "file_renamed");
|
load_module_test("tests-pl/issue_rename_file.pl", "file_renamed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue #3262: read/1 on non-TTY stdin should resolve without requiring a newline
|
||||||
|
#[test]
|
||||||
|
#[cfg_attr(miri, ignore = "unsupported operation when isolation is enabled")]
|
||||||
|
fn issue3262_read_from_stdin_no_newline() {
|
||||||
|
load_module_test_with_input("tests-pl/issue3262.pl", "hello.", "hello");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|||||||
Reference in New Issue
Block a user