Skip to content

Commit 4592787

Browse files
authored
get_inheritable, dup for windows (RustPython#6343)
1 parent 8ad7f91 commit 4592787

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

Lib/test/test_builtin.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,6 @@ def test_open_default_encoding(self):
13581358
os.environ.clear()
13591359
os.environ.update(old_environ)
13601360

1361-
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON Windows')
13621361
@support.requires_subprocess()
13631362
def test_open_non_inheritable(self):
13641363
fileobj = open(__file__, encoding="utf-8")

Lib/test/test_os.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,6 @@ def test_urandom_failure(self):
21022102
"""
21032103
assert_python_ok('-c', code)
21042104

2105-
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; on Windows (ModuleNotFoundError: No module named 'os')")
21062105
def test_urandom_fd_closed(self):
21072106
# Issue #21207: urandom() should reopen its fd to /dev/urandom if
21082107
# closed.
@@ -4621,7 +4620,6 @@ def test_process_cpu_count_affinity(self):
46214620
# FD inheritance check is only useful for systems with process support.
46224621
@support.requires_subprocess()
46234622
class FDInheritanceTests(unittest.TestCase):
4624-
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; os.get_inheritable not implemented yet for all platforms')
46254623
def test_get_set_inheritable(self):
46264624
fd = os.open(__file__, os.O_RDONLY)
46274625
self.addCleanup(os.close, fd)
@@ -4682,7 +4680,6 @@ def test_get_set_inheritable_badf(self):
46824680
os.set_inheritable(fd, False)
46834681
self.assertEqual(ctx.exception.errno, errno.EBADF)
46844682

4685-
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; os.get_inheritable not implemented yet for all platforms')
46864683
def test_open(self):
46874684
fd = os.open(__file__, os.O_RDONLY)
46884685
self.addCleanup(os.close, fd)
@@ -4696,7 +4693,6 @@ def test_pipe(self):
46964693
self.assertEqual(os.get_inheritable(rfd), False)
46974694
self.assertEqual(os.get_inheritable(wfd), False)
46984695

4699-
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; os.dup on windows')
47004696
def test_dup(self):
47014697
fd1 = os.open(__file__, os.O_RDONLY)
47024698
self.addCleanup(os.close, fd1)
@@ -4705,13 +4701,11 @@ def test_dup(self):
47054701
self.addCleanup(os.close, fd2)
47064702
self.assertEqual(os.get_inheritable(fd2), False)
47074703

4708-
@unittest.skipIf(sys.platform == 'win32', 'TODO: RUSTPYTHON; os.dup on windows')
47094704
def test_dup_standard_stream(self):
47104705
fd = os.dup(1)
47114706
self.addCleanup(os.close, fd)
47124707
self.assertGreater(fd, 0)
47134708

4714-
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; os.dup not implemented yet for all platforms')
47154709
@unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
47164710
def test_dup_nul(self):
47174711
# os.dup() was creating inheritable fds for character files.

crates/vm/src/stdlib/nt.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyRef<PyModule> {
1414
pub(crate) mod module {
1515
use crate::{
1616
PyResult, TryFromObject, VirtualMachine,
17-
builtins::{PyDictRef, PyListRef, PyStrRef, PyTupleRef},
17+
builtins::{PyBaseExceptionRef, PyDictRef, PyListRef, PyStrRef, PyTupleRef},
1818
common::{crt_fd, os::last_os_error, suppress_iph},
1919
convert::ToPyException,
2020
function::{Either, OptionalArg},
@@ -391,6 +391,13 @@ pub(crate) mod module {
391391
}
392392
}
393393

394+
#[pyfunction]
395+
fn get_inheritable(fd: i32, vm: &VirtualMachine) -> PyResult<bool> {
396+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(fd) };
397+
let handle = crt_fd::as_handle(borrowed).map_err(|e| e.to_pyexception(vm))?;
398+
get_handle_inheritable(handle.as_raw_handle() as _, vm)
399+
}
400+
394401
#[pyfunction]
395402
fn getlogin(vm: &VirtualMachine) -> PyResult<String> {
396403
let mut buffer = [0u16; 257];
@@ -477,6 +484,15 @@ pub(crate) mod module {
477484

478485
unsafe extern "C" {
479486
fn _umask(mask: i32) -> i32;
487+
fn _dup(fd: i32) -> i32;
488+
fn _dup2(fd: i32, fd2: i32) -> i32;
489+
}
490+
491+
/// Close fd and convert error to PyException (PEP 446 cleanup)
492+
#[cold]
493+
fn close_fd_and_raise(fd: i32, err: std::io::Error, vm: &VirtualMachine) -> PyBaseExceptionRef {
494+
let _ = unsafe { crt_fd::Owned::from_raw(fd) };
495+
err.to_pyexception(vm)
480496
}
481497

482498
#[pyfunction]
@@ -489,6 +505,45 @@ pub(crate) mod module {
489505
}
490506
}
491507

508+
#[pyfunction]
509+
fn dup(fd: i32, vm: &VirtualMachine) -> PyResult<i32> {
510+
let fd2 = unsafe { suppress_iph!(_dup(fd)) };
511+
if fd2 < 0 {
512+
return Err(errno_err(vm));
513+
}
514+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(fd2) };
515+
let handle = crt_fd::as_handle(borrowed).map_err(|e| close_fd_and_raise(fd2, e, vm))?;
516+
raw_set_handle_inheritable(handle.as_raw_handle() as _, false)
517+
.map_err(|e| close_fd_and_raise(fd2, e, vm))?;
518+
Ok(fd2)
519+
}
520+
521+
#[derive(FromArgs)]
522+
struct Dup2Args {
523+
#[pyarg(positional)]
524+
fd: i32,
525+
#[pyarg(positional)]
526+
fd2: i32,
527+
#[pyarg(any, default = true)]
528+
inheritable: bool,
529+
}
530+
531+
#[pyfunction]
532+
fn dup2(args: Dup2Args, vm: &VirtualMachine) -> PyResult<i32> {
533+
let result = unsafe { suppress_iph!(_dup2(args.fd, args.fd2)) };
534+
if result < 0 {
535+
return Err(errno_err(vm));
536+
}
537+
if !args.inheritable {
538+
let borrowed = unsafe { crt_fd::Borrowed::borrow_raw(args.fd2) };
539+
let handle =
540+
crt_fd::as_handle(borrowed).map_err(|e| close_fd_and_raise(args.fd2, e, vm))?;
541+
raw_set_handle_inheritable(handle.as_raw_handle() as _, false)
542+
.map_err(|e| close_fd_and_raise(args.fd2, e, vm))?;
543+
}
544+
Ok(args.fd2)
545+
}
546+
492547
pub(crate) fn support_funcs() -> Vec<SupportFunc> {
493548
Vec::new()
494549
}

0 commit comments

Comments
 (0)