Skip to content

Commit 0038b58

Browse files
authored
[3.13] gh-143698: correctly check scheduler and setpgroup values for os.posix_spawn[p] (GH-143699) (#145074)
* [3.13] gh-143698: correctly check `scheduler` and `setpgroup` values for `os.posix_spawn[p]` (GH-143699) Fix an issue where passing invalid arguments to `os.posix_spawn[p]` functions raised a SystemError instead of a TypeError, and allow to explicitly use `None` for `scheduler` and `setpgroup` as specified in the docs. (cherry picked from commit 347fc43)
1 parent 773cd81 commit 0038b58

File tree

6 files changed

+46
-15
lines changed

6 files changed

+46
-15
lines changed

Lib/test/test_inspect/test_inspect.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6293,8 +6293,7 @@ def test_operator_module_has_signatures(self):
62936293
def test_os_module_has_signatures(self):
62946294
unsupported_signature = {'chmod', 'utime'}
62956295
unsupported_signature |= {name for name in
6296-
['get_terminal_size', 'posix_spawn', 'posix_spawnp',
6297-
'register_at_fork', 'startfile']
6296+
['get_terminal_size', 'register_at_fork', 'startfile']
62986297
if hasattr(os, name)}
62996298
self._test_module_has_signatures(os, unsupported_signature=unsupported_signature)
63006299

Lib/test/test_posix.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,11 @@ def test_setpgroup(self):
18881888
)
18891889
support.wait_process(pid, exitcode=0)
18901890

1891+
def test_setpgroup_allow_none(self):
1892+
path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
1893+
pid = self.spawn_func(path, args, os.environ, setpgroup=None)
1894+
support.wait_process(pid, exitcode=0)
1895+
18911896
def test_setpgroup_wrong_type(self):
18921897
with self.assertRaises(TypeError):
18931898
self.spawn_func(sys.executable,
@@ -1988,6 +1993,20 @@ def test_setsigdef_wrong_type(self):
19881993
[sys.executable, "-c", "pass"],
19891994
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
19901995

1996+
def test_scheduler_allow_none(self):
1997+
path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
1998+
pid = self.spawn_func(path, args, os.environ, scheduler=None)
1999+
support.wait_process(pid, exitcode=0)
2000+
2001+
@support.subTests("scheduler", [object(), 1, [1, 2]])
2002+
def test_scheduler_wrong_type(self, scheduler):
2003+
path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
2004+
with self.assertRaisesRegex(
2005+
TypeError,
2006+
"scheduler must be a tuple or None",
2007+
):
2008+
self.spawn_func(path, args, os.environ, scheduler=scheduler)
2009+
19912010
@requires_sched
19922011
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
19932012
"bpo-34685: test can fail on BSD")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Raise :exc:`TypeError` instead of :exc:`SystemError` when the *scheduler*
2+
in :func:`os.posix_spawn` or :func:`os.posix_spawnp` is not a tuple.
3+
Patch by Bénédikt Tran.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Allow *scheduler* and *setpgroup* arguments to be explicitly :const:`None`
2+
when calling :func:`os.posix_spawn` or :func:`os.posix_spawnp`. Patch by
3+
Bénédikt Tran.

Modules/clinic/posixmodule.c.h

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7060,6 +7060,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg
70607060
PyObject *setsigdef, PyObject *scheduler,
70617061
posix_spawnattr_t *attrp)
70627062
{
7063+
assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
70637064
long all_flags = 0;
70647065

70657066
errno = posix_spawnattr_init(attrp);
@@ -7068,7 +7069,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg
70687069
return -1;
70697070
}
70707071

7071-
if (setpgroup) {
7072+
if (setpgroup && setpgroup != Py_None) {
70727073
pid_t pgid = PyLong_AsPid(setpgroup);
70737074
if (pgid == (pid_t)-1 && PyErr_Occurred()) {
70747075
goto fail;
@@ -7141,7 +7142,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg
71417142
}
71427143
#endif
71437144

7144-
if (scheduler) {
7145+
if (scheduler && scheduler != Py_None) {
71457146
#ifdef POSIX_SPAWN_SETSCHEDULER
71467147
PyObject *py_schedpolicy;
71477148
PyObject *schedparam_obj;
@@ -7366,6 +7367,12 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
73667367
goto exit;
73677368
}
73687369

7370+
if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7371+
PyErr_Format(PyExc_TypeError,
7372+
"%s: scheduler must be a tuple or None", func_name);
7373+
goto exit;
7374+
}
7375+
73697376
argvlist = parse_arglist(argv, &argc);
73707377
if (argvlist == NULL) {
73717378
goto exit;
@@ -7477,7 +7484,7 @@ os.posix_spawn
74777484
*
74787485
file_actions: object(c_default='NULL') = ()
74797486
A sequence of file action tuples.
7480-
setpgroup: object = NULL
7487+
setpgroup: object(c_default='NULL') = None
74817488
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
74827489
resetids: bool = False
74837490
If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
@@ -7487,7 +7494,7 @@ os.posix_spawn
74877494
The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
74887495
setsigdef: object(c_default='NULL') = ()
74897496
The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7490-
scheduler: object = NULL
7497+
scheduler: object(c_default='NULL') = None
74917498
A tuple with the scheduler policy (optional) and parameters.
74927499
74937500
Execute the program specified by path in a new process.
@@ -7499,7 +7506,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
74997506
PyObject *setpgroup, int resetids, int setsid,
75007507
PyObject *setsigmask, PyObject *setsigdef,
75017508
PyObject *scheduler)
7502-
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
7509+
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
75037510
{
75047511
return py_posix_spawn(0, module, path, argv, env, file_actions,
75057512
setpgroup, resetids, setsid, setsigmask, setsigdef,
@@ -7523,7 +7530,7 @@ os.posix_spawnp
75237530
*
75247531
file_actions: object(c_default='NULL') = ()
75257532
A sequence of file action tuples.
7526-
setpgroup: object = NULL
7533+
setpgroup: object(c_default='NULL') = None
75277534
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
75287535
resetids: bool = False
75297536
If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
@@ -7533,7 +7540,7 @@ os.posix_spawnp
75337540
The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
75347541
setsigdef: object(c_default='NULL') = ()
75357542
The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7536-
scheduler: object = NULL
7543+
scheduler: object(c_default='NULL') = None
75377544
A tuple with the scheduler policy (optional) and parameters.
75387545
75397546
Execute the program specified by path in a new process.
@@ -7545,7 +7552,7 @@ os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
75457552
PyObject *setpgroup, int resetids, int setsid,
75467553
PyObject *setsigmask, PyObject *setsigdef,
75477554
PyObject *scheduler)
7548-
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7555+
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
75497556
{
75507557
return py_posix_spawn(1, module, path, argv, env, file_actions,
75517558
setpgroup, resetids, setsid, setsigmask, setsigdef,

0 commit comments

Comments
 (0)