Skip to content

Commit 7473a43

Browse files
authored
Fix posix tests (#5811)
1 parent f31ebf8 commit 7473a43

File tree

2 files changed

+103
-26
lines changed

2 files changed

+103
-26
lines changed

Lib/test/test_posix.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,8 +1730,6 @@ def test_no_such_executable(self):
17301730
self.assertEqual(pid2, pid)
17311731
self.assertNotEqual(status, 0)
17321732

1733-
# TODO: RUSTPYTHON: TypeError: '_Environ' object is not a mapping
1734-
@unittest.expectedFailure
17351733
def test_specify_environment(self):
17361734
envfile = os_helper.TESTFN
17371735
self.addCleanup(os_helper.unlink, envfile)
@@ -1765,8 +1763,6 @@ def test_empty_file_actions(self):
17651763
)
17661764
support.wait_process(pid, exitcode=0)
17671765

1768-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument resetids
1769-
@unittest.expectedFailure
17701766
def test_resetids_explicit_default(self):
17711767
pid = self.spawn_func(
17721768
sys.executable,
@@ -1776,8 +1772,6 @@ def test_resetids_explicit_default(self):
17761772
)
17771773
support.wait_process(pid, exitcode=0)
17781774

1779-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument resetids
1780-
@unittest.expectedFailure
17811775
def test_resetids(self):
17821776
pid = self.spawn_func(
17831777
sys.executable,
@@ -1787,8 +1781,6 @@ def test_resetids(self):
17871781
)
17881782
support.wait_process(pid, exitcode=0)
17891783

1790-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument setpgroup
1791-
@unittest.expectedFailure
17921784
def test_setpgroup(self):
17931785
pid = self.spawn_func(
17941786
sys.executable,
@@ -1819,8 +1811,6 @@ def test_setsigmask(self):
18191811
)
18201812
support.wait_process(pid, exitcode=0)
18211813

1822-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument setsigmask
1823-
@unittest.expectedFailure
18241814
def test_setsigmask_wrong_type(self):
18251815
with self.assertRaises(TypeError):
18261816
self.spawn_func(sys.executable,
@@ -1836,8 +1826,6 @@ def test_setsigmask_wrong_type(self):
18361826
os.environ, setsigmask=[signal.NSIG,
18371827
signal.NSIG+1])
18381828

1839-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument setsid
1840-
@unittest.expectedFailure
18411829
def test_setsid(self):
18421830
rfd, wfd = os.pipe()
18431831
self.addCleanup(os.close, rfd)
@@ -1902,7 +1890,6 @@ def test_setsigdef_wrong_type(self):
19021890
[sys.executable, "-c", "pass"],
19031891
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
19041892

1905-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument scheduler
19061893
@unittest.expectedFailure
19071894
@requires_sched
19081895
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
@@ -1924,7 +1911,6 @@ def test_setscheduler_only_param(self):
19241911
)
19251912
support.wait_process(pid, exitcode=0)
19261913

1927-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument scheduler
19281914
@unittest.expectedFailure
19291915
@requires_sched
19301916
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),

vm/src/stdlib/posix.rs

Lines changed: 103 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,20 +1308,33 @@ pub mod module {
13081308
env: crate::function::ArgMapping,
13091309
vm: &VirtualMachine,
13101310
) -> PyResult<Vec<CString>> {
1311-
let keys = env.mapping().keys(vm)?;
1312-
let values = env.mapping().values(vm)?;
1311+
let items = env.mapping().items(vm)?;
13131312

1314-
let keys = PyListRef::try_from_object(vm, keys)
1315-
.map_err(|_| vm.new_type_error("env.keys() is not a list".to_owned()))?
1316-
.borrow_vec()
1317-
.to_vec();
1318-
let values = PyListRef::try_from_object(vm, values)
1319-
.map_err(|_| vm.new_type_error("env.values() is not a list".to_owned()))?
1320-
.borrow_vec()
1321-
.to_vec();
1313+
// Convert items to list if it isn't already
1314+
let items = vm.ctx.new_list(
1315+
items
1316+
.get_iter(vm)?
1317+
.iter(vm)?
1318+
.collect::<PyResult<Vec<_>>>()?,
1319+
);
13221320

1323-
keys.into_iter()
1324-
.zip(values)
1321+
items
1322+
.borrow_vec()
1323+
.iter()
1324+
.map(|item| {
1325+
let tuple = item
1326+
.downcast_ref::<crate::builtins::PyTuple>()
1327+
.ok_or_else(|| vm.new_type_error("items() should return tuples".to_owned()))?;
1328+
let tuple_items = tuple.as_slice();
1329+
if tuple_items.len() != 2 {
1330+
return Err(vm.new_value_error(
1331+
"items() tuples should have exactly 2 elements".to_owned(),
1332+
));
1333+
}
1334+
Ok((tuple_items[0].clone(), tuple_items[1].clone()))
1335+
})
1336+
.collect::<PyResult<Vec<_>>>()?
1337+
.into_iter()
13251338
.map(|(k, v)| {
13261339
let k = OsPath::try_from_object(vm, k)?.into_bytes();
13271340
let v = OsPath::try_from_object(vm, v)?.into_bytes();
@@ -1361,6 +1374,16 @@ pub mod module {
13611374
file_actions: Option<crate::function::ArgIterable<PyTupleRef>>,
13621375
#[pyarg(named, default)]
13631376
setsigdef: Option<crate::function::ArgIterable<i32>>,
1377+
#[pyarg(named, default)]
1378+
setpgroup: Option<libc::pid_t>,
1379+
#[pyarg(named, default)]
1380+
resetids: bool,
1381+
#[pyarg(named, default)]
1382+
setsid: bool,
1383+
#[pyarg(named, default)]
1384+
setsigmask: Option<crate::function::ArgIterable<i32>>,
1385+
#[pyarg(named, default)]
1386+
scheduler: Option<PyTupleRef>,
13641387
}
13651388

13661389
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))]
@@ -1459,6 +1482,74 @@ pub mod module {
14591482
);
14601483
}
14611484

1485+
// Handle new posix_spawn attributes
1486+
let mut flags = 0i32;
1487+
1488+
if let Some(pgid) = self.setpgroup {
1489+
let ret = unsafe { libc::posix_spawnattr_setpgroup(&mut attrp, pgid) };
1490+
if ret != 0 {
1491+
return Err(vm.new_os_error(format!("posix_spawnattr_setpgroup failed: {ret}")));
1492+
}
1493+
flags |= libc::POSIX_SPAWN_SETPGROUP;
1494+
}
1495+
1496+
if self.resetids {
1497+
flags |= libc::POSIX_SPAWN_RESETIDS;
1498+
}
1499+
1500+
if self.setsid {
1501+
// Note: POSIX_SPAWN_SETSID may not be available on all platforms
1502+
#[cfg(target_os = "linux")]
1503+
{
1504+
flags |= 0x0080; // POSIX_SPAWN_SETSID value on Linux
1505+
}
1506+
#[cfg(not(target_os = "linux"))]
1507+
{
1508+
return Err(vm.new_not_implemented_error(
1509+
"setsid parameter is not supported on this platform".to_owned(),
1510+
));
1511+
}
1512+
}
1513+
1514+
if let Some(sigs) = self.setsigmask {
1515+
use nix::sys::signal;
1516+
let mut set = signal::SigSet::empty();
1517+
for sig in sigs.iter(vm)? {
1518+
let sig = sig?;
1519+
let sig = signal::Signal::try_from(sig).map_err(|_| {
1520+
vm.new_value_error(format!("signal number {sig} out of range"))
1521+
})?;
1522+
set.add(sig);
1523+
}
1524+
let ret = unsafe { libc::posix_spawnattr_setsigmask(&mut attrp, set.as_ref()) };
1525+
if ret != 0 {
1526+
return Err(
1527+
vm.new_os_error(format!("posix_spawnattr_setsigmask failed: {ret}"))
1528+
);
1529+
}
1530+
flags |= libc::POSIX_SPAWN_SETSIGMASK;
1531+
}
1532+
1533+
if let Some(_scheduler) = self.scheduler {
1534+
// TODO: Implement scheduler parameter handling
1535+
// This requires platform-specific sched_param struct handling
1536+
return Err(vm.new_not_implemented_error(
1537+
"scheduler parameter is not yet implemented".to_owned(),
1538+
));
1539+
}
1540+
1541+
if flags != 0 {
1542+
// Check for potential overflow when casting to c_short
1543+
if flags > libc::c_short::MAX as i32 {
1544+
return Err(vm.new_value_error("Too many flags set for posix_spawn".to_owned()));
1545+
}
1546+
let ret =
1547+
unsafe { libc::posix_spawnattr_setflags(&mut attrp, flags as libc::c_short) };
1548+
if ret != 0 {
1549+
return Err(vm.new_os_error(format!("posix_spawnattr_setflags failed: {ret}")));
1550+
}
1551+
}
1552+
14621553
let mut args: Vec<CString> = self
14631554
.args
14641555
.iter(vm)?

0 commit comments

Comments
 (0)