Skip to content

Commit 26b3445

Browse files
authored
windows pipe/getppid (#6378)
* pipe/pid * libc first
1 parent 8bc46cf commit 26b3445

File tree

4 files changed

+112
-20
lines changed

4 files changed

+112
-20
lines changed

Lib/test/test_subprocess.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,6 @@ def test_communicate_returns(self):
10161016
self.assertEqual(stdout, None)
10171017
self.assertEqual(stderr, None)
10181018

1019-
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON")
10201019
def test_communicate_pipe_buf(self):
10211020
# communicate() with writes larger than pipe_buf
10221021
# This test will probably deadlock rather than fail, if
@@ -3564,8 +3563,6 @@ def test_close_fds(self):
35643563
close_fds=True)
35653564
self.assertEqual(rc, 47)
35663565

3567-
# TODO: RUSTPYTHON
3568-
@unittest.expectedFailure
35693566
def test_close_fds_with_stdio(self):
35703567
import msvcrt
35713568

crates/common/src/fileutils.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -460,22 +460,16 @@ pub fn fopen(path: &std::path::Path, mode: &str) -> std::io::Result<*mut libc::F
460460
{
461461
use std::os::windows::io::IntoRawHandle;
462462

463-
// Declare Windows CRT functions
464-
unsafe extern "C" {
465-
fn _open_osfhandle(handle: isize, flags: libc::c_int) -> libc::c_int;
466-
fn _fdopen(fd: libc::c_int, mode: *const libc::c_char) -> *mut libc::FILE;
467-
}
468-
469463
// Convert File handle to CRT file descriptor
470464
let handle = file.into_raw_handle();
471-
let fd = unsafe { _open_osfhandle(handle as isize, libc::O_RDONLY) };
465+
let fd = unsafe { libc::open_osfhandle(handle as isize, libc::O_RDONLY) };
472466
if fd == -1 {
473467
return Err(std::io::Error::last_os_error());
474468
}
475469

476470
// Convert fd to FILE*
477471
let mode_cstr = CString::new(mode).unwrap();
478-
let fp = unsafe { _fdopen(fd, mode_cstr.as_ptr()) };
472+
let fp = unsafe { libc::fdopen(fd, mode_cstr.as_ptr()) };
479473
if fp.is_null() {
480474
unsafe { libc::close(fd) };
481475
return Err(std::io::Error::last_os_error());

crates/vm/src/stdlib/msvcrt.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,9 @@ mod msvcrt {
8888
}
8989
}
9090

91-
unsafe extern "C" {
92-
fn _open_osfhandle(osfhandle: isize, flags: i32) -> i32;
93-
}
94-
9591
#[pyfunction]
9692
fn open_osfhandle(handle: isize, flags: i32, vm: &VirtualMachine) -> PyResult<i32> {
97-
let ret = unsafe { suppress_iph!(_open_osfhandle(handle, flags)) };
93+
let ret = unsafe { suppress_iph!(libc::open_osfhandle(handle, flags)) };
9894
if ret == -1 {
9995
Err(errno_err(vm))
10096
} else {

crates/vm/src/stdlib/nt.rs

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -850,8 +850,6 @@ pub(crate) mod module {
850850

851851
unsafe extern "C" {
852852
fn _umask(mask: i32) -> i32;
853-
fn _dup(fd: i32) -> i32;
854-
fn _dup2(fd: i32, fd2: i32) -> i32;
855853
}
856854

857855
/// Close fd and convert error to PyException (PEP 446 cleanup)
@@ -871,9 +869,116 @@ pub(crate) mod module {
871869
}
872870
}
873871

872+
#[pyfunction]
873+
fn pipe(vm: &VirtualMachine) -> PyResult<(i32, i32)> {
874+
use windows_sys::Win32::System::Pipes::CreatePipe;
875+
876+
let (read_handle, write_handle) = unsafe {
877+
let mut read = MaybeUninit::<isize>::uninit();
878+
let mut write = MaybeUninit::<isize>::uninit();
879+
let res = CreatePipe(
880+
read.as_mut_ptr() as *mut _,
881+
write.as_mut_ptr() as *mut _,
882+
std::ptr::null(),
883+
0,
884+
);
885+
if res == 0 {
886+
return Err(errno_err(vm));
887+
}
888+
(read.assume_init(), write.assume_init())
889+
};
890+
891+
// Convert handles to file descriptors
892+
// O_NOINHERIT = 0x80 (MSVC CRT)
893+
const O_NOINHERIT: i32 = 0x80;
894+
let read_fd = unsafe { libc::open_osfhandle(read_handle, O_NOINHERIT) };
895+
let write_fd = unsafe { libc::open_osfhandle(write_handle, libc::O_WRONLY | O_NOINHERIT) };
896+
897+
if read_fd == -1 || write_fd == -1 {
898+
unsafe {
899+
Foundation::CloseHandle(read_handle as _);
900+
Foundation::CloseHandle(write_handle as _);
901+
}
902+
return Err(errno_err(vm));
903+
}
904+
905+
Ok((read_fd, write_fd))
906+
}
907+
908+
#[pyfunction]
909+
fn getppid() -> u32 {
910+
use windows_sys::Win32::System::Threading::GetCurrentProcess;
911+
912+
#[repr(C)]
913+
struct ProcessBasicInformation {
914+
exit_status: isize,
915+
peb_base_address: *mut std::ffi::c_void,
916+
affinity_mask: usize,
917+
base_priority: i32,
918+
unique_process_id: usize,
919+
inherited_from_unique_process_id: usize,
920+
}
921+
922+
type NtQueryInformationProcessFn = unsafe extern "system" fn(
923+
process_handle: isize,
924+
process_information_class: u32,
925+
process_information: *mut std::ffi::c_void,
926+
process_information_length: u32,
927+
return_length: *mut u32,
928+
) -> i32;
929+
930+
let ntdll = unsafe {
931+
windows_sys::Win32::System::LibraryLoader::GetModuleHandleW(windows_sys::w!(
932+
"ntdll.dll"
933+
))
934+
};
935+
if ntdll.is_null() {
936+
return 0;
937+
}
938+
939+
let func = unsafe {
940+
windows_sys::Win32::System::LibraryLoader::GetProcAddress(
941+
ntdll,
942+
c"NtQueryInformationProcess".as_ptr() as *const u8,
943+
)
944+
};
945+
let Some(func) = func else {
946+
return 0;
947+
};
948+
let nt_query: NtQueryInformationProcessFn = unsafe { std::mem::transmute(func) };
949+
950+
let mut info = ProcessBasicInformation {
951+
exit_status: 0,
952+
peb_base_address: std::ptr::null_mut(),
953+
affinity_mask: 0,
954+
base_priority: 0,
955+
unique_process_id: 0,
956+
inherited_from_unique_process_id: 0,
957+
};
958+
959+
let status = unsafe {
960+
nt_query(
961+
GetCurrentProcess() as isize,
962+
0, // ProcessBasicInformation
963+
&mut info as *mut _ as *mut std::ffi::c_void,
964+
std::mem::size_of::<ProcessBasicInformation>() as u32,
965+
std::ptr::null_mut(),
966+
)
967+
};
968+
969+
if status >= 0
970+
&& info.inherited_from_unique_process_id != 0
971+
&& info.inherited_from_unique_process_id < u32::MAX as usize
972+
{
973+
info.inherited_from_unique_process_id as u32
974+
} else {
975+
0
976+
}
977+
}
978+
874979
#[pyfunction]
875980
fn dup(fd: i32, vm: &VirtualMachine) -> PyResult<i32> {
876-
let fd2 = unsafe { suppress_iph!(_dup(fd)) };
981+
let fd2 = unsafe { suppress_iph!(libc::dup(fd)) };
877982
if fd2 < 0 {
878983
return Err(errno_err(vm));
879984
}
@@ -896,7 +1001,7 @@ pub(crate) mod module {
8961001

8971002
#[pyfunction]
8981003
fn dup2(args: Dup2Args, vm: &VirtualMachine) -> PyResult<i32> {
899-
let result = unsafe { suppress_iph!(_dup2(args.fd, args.fd2)) };
1004+
let result = unsafe { suppress_iph!(libc::dup2(args.fd, args.fd2)) };
9001005
if result < 0 {
9011006
return Err(errno_err(vm));
9021007
}

0 commit comments

Comments
 (0)