Skip to content

Commit dcf96d0

Browse files
authored
[3.14] gh-143698: correctly check scheduler and setpgroup values for os.posix_spawn[p] (GH-143699) (#145073)
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 8e482eb commit dcf96d0

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
@@ -6203,8 +6203,7 @@ def test_operator_module_has_signatures(self):
62036203
def test_os_module_has_signatures(self):
62046204
unsupported_signature = {'chmod', 'utime'}
62056205
unsupported_signature |= {name for name in
6206-
['get_terminal_size', 'link', 'posix_spawn', 'posix_spawnp',
6207-
'register_at_fork', 'startfile']
6206+
['get_terminal_size', 'link', 'register_at_fork', 'startfile']
62086207
if hasattr(os, name)}
62096208
self._test_module_has_signatures(os, unsupported_signature=unsupported_signature)
62106209

Lib/test/test_posix.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,11 @@ def test_setpgroup(self):
19331933
)
19341934
support.wait_process(pid, exitcode=0)
19351935

1936+
def test_setpgroup_allow_none(self):
1937+
path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
1938+
pid = self.spawn_func(path, args, os.environ, setpgroup=None)
1939+
support.wait_process(pid, exitcode=0)
1940+
19361941
def test_setpgroup_wrong_type(self):
19371942
with self.assertRaises(TypeError):
19381943
self.spawn_func(sys.executable,
@@ -2033,6 +2038,20 @@ def test_setsigdef_wrong_type(self):
20332038
[sys.executable, "-c", "pass"],
20342039
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
20352040

2041+
def test_scheduler_allow_none(self):
2042+
path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
2043+
pid = self.spawn_func(path, args, os.environ, scheduler=None)
2044+
support.wait_process(pid, exitcode=0)
2045+
2046+
@support.subTests("scheduler", [object(), 1, [1, 2]])
2047+
def test_scheduler_wrong_type(self, scheduler):
2048+
path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
2049+
with self.assertRaisesRegex(
2050+
TypeError,
2051+
"scheduler must be a tuple or None",
2052+
):
2053+
self.spawn_func(path, args, os.environ, scheduler=scheduler)
2054+
20362055
@requires_sched
20372056
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
20382057
"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
@@ -7155,6 +7155,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg
71557155
PyObject *setsigdef, PyObject *scheduler,
71567156
posix_spawnattr_t *attrp)
71577157
{
7158+
assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
71587159
long all_flags = 0;
71597160

71607161
errno = posix_spawnattr_init(attrp);
@@ -7163,7 +7164,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg
71637164
return -1;
71647165
}
71657166

7166-
if (setpgroup) {
7167+
if (setpgroup && setpgroup != Py_None) {
71677168
pid_t pgid = PyLong_AsPid(setpgroup);
71687169
if (pgid == (pid_t)-1 && PyErr_Occurred()) {
71697170
goto fail;
@@ -7236,7 +7237,7 @@ parse_posix_spawn_flags(PyObject *module, const char *func_name, PyObject *setpg
72367237
}
72377238
#endif
72387239

7239-
if (scheduler) {
7240+
if (scheduler && scheduler != Py_None) {
72407241
#ifdef POSIX_SPAWN_SETSCHEDULER
72417242
PyObject *py_schedpolicy;
72427243
PyObject *schedparam_obj;
@@ -7461,6 +7462,12 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
74617462
goto exit;
74627463
}
74637464

7465+
if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
7466+
PyErr_Format(PyExc_TypeError,
7467+
"%s: scheduler must be a tuple or None", func_name);
7468+
goto exit;
7469+
}
7470+
74647471
argvlist = parse_arglist(argv, &argc);
74657472
if (argvlist == NULL) {
74667473
goto exit;
@@ -7572,7 +7579,7 @@ os.posix_spawn
75727579
*
75737580
file_actions: object(c_default='NULL') = ()
75747581
A sequence of file action tuples.
7575-
setpgroup: object = NULL
7582+
setpgroup: object(c_default='NULL') = None
75767583
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
75777584
resetids: bool = False
75787585
If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
@@ -7582,7 +7589,7 @@ os.posix_spawn
75827589
The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
75837590
setsigdef: object(c_default='NULL') = ()
75847591
The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7585-
scheduler: object = NULL
7592+
scheduler: object(c_default='NULL') = None
75867593
A tuple with the scheduler policy (optional) and parameters.
75877594
75887595
Execute the program specified by path in a new process.
@@ -7594,7 +7601,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
75947601
PyObject *setpgroup, int resetids, int setsid,
75957602
PyObject *setsigmask, PyObject *setsigdef,
75967603
PyObject *scheduler)
7597-
/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
7604+
/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
75987605
{
75997606
return py_posix_spawn(0, module, path, argv, env, file_actions,
76007607
setpgroup, resetids, setsid, setsigmask, setsigdef,
@@ -7618,7 +7625,7 @@ os.posix_spawnp
76187625
*
76197626
file_actions: object(c_default='NULL') = ()
76207627
A sequence of file action tuples.
7621-
setpgroup: object = NULL
7628+
setpgroup: object(c_default='NULL') = None
76227629
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
76237630
resetids: bool = False
76247631
If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
@@ -7628,7 +7635,7 @@ os.posix_spawnp
76287635
The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
76297636
setsigdef: object(c_default='NULL') = ()
76307637
The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
7631-
scheduler: object = NULL
7638+
scheduler: object(c_default='NULL') = None
76327639
A tuple with the scheduler policy (optional) and parameters.
76337640
76347641
Execute the program specified by path in a new process.
@@ -7640,7 +7647,7 @@ os_posix_spawnp_impl(PyObject *module, path_t *path, PyObject *argv,
76407647
PyObject *setpgroup, int resetids, int setsid,
76417648
PyObject *setsigmask, PyObject *setsigdef,
76427649
PyObject *scheduler)
7643-
/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
7650+
/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
76447651
{
76457652
return py_posix_spawn(1, module, path, argv, env, file_actions,
76467653
setpgroup, resetids, setsid, setsigmask, setsigdef,

0 commit comments

Comments
 (0)