def test_os_module_has_signatures(self):
unsupported_signature = {'chmod', 'utime'}
unsupported_signature |= {name for name in
- ['get_terminal_size', 'link', 'posix_spawn', 'posix_spawnp',
- 'register_at_fork', 'startfile']
+ ['get_terminal_size', 'link', 'register_at_fork', 'startfile']
if hasattr(os, name)}
self._test_module_has_signatures(os, unsupported_signature=unsupported_signature)
)
support.wait_process(pid, exitcode=0)
+ def test_setpgroup_allow_none(self):
+ path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
+ pid = self.spawn_func(path, args, os.environ, setpgroup=None)
+ support.wait_process(pid, exitcode=0)
+
def test_setpgroup_wrong_type(self):
with self.assertRaises(TypeError):
self.spawn_func(sys.executable,
[sys.executable, "-c", "pass"],
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
+ def test_scheduler_allow_none(self):
+ path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
+ pid = self.spawn_func(path, args, os.environ, scheduler=None)
+ support.wait_process(pid, exitcode=0)
+
+ @support.subTests("scheduler", [object(), 1, [1, 2]])
+ def test_scheduler_wrong_type(self, scheduler):
+ path, args = self.NOOP_PROGRAM[0], self.NOOP_PROGRAM
+ with self.assertRaisesRegex(
+ TypeError,
+ "scheduler must be a tuple or None",
+ ):
+ self.spawn_func(path, args, os.environ, scheduler=scheduler)
+
@requires_sched
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
"bpo-34685: test can fail on BSD")
--- /dev/null
+Raise :exc:`TypeError` instead of :exc:`SystemError` when the *scheduler*
+in :func:`os.posix_spawn` or :func:`os.posix_spawnp` is not a tuple.
+Patch by Bénédikt Tran.
--- /dev/null
+Allow *scheduler* and *setpgroup* arguments to be explicitly :const:`None`
+when calling :func:`os.posix_spawn` or :func:`os.posix_spawnp`. Patch by
+Bénédikt Tran.
PyDoc_STRVAR(os_posix_spawn__doc__,
"posix_spawn($module, path, argv, env, /, *, file_actions=(),\n"
-" setpgroup=<unrepresentable>, resetids=False, setsid=False,\n"
-" setsigmask=(), setsigdef=(), scheduler=<unrepresentable>)\n"
+" setpgroup=None, resetids=False, setsid=False,\n"
+" setsigmask=(), setsigdef=(), scheduler=None)\n"
"--\n"
"\n"
"Execute the program specified by path in a new process.\n"
PyDoc_STRVAR(os_posix_spawnp__doc__,
"posix_spawnp($module, path, argv, env, /, *, file_actions=(),\n"
-" setpgroup=<unrepresentable>, resetids=False, setsid=False,\n"
-" setsigmask=(), setsigdef=(), scheduler=<unrepresentable>)\n"
+" setpgroup=None, resetids=False, setsid=False,\n"
+" setsigmask=(), setsigdef=(), scheduler=None)\n"
"--\n"
"\n"
"Execute the program specified by path in a new process.\n"
#ifndef OS__EMSCRIPTEN_LOG_METHODDEF
#define OS__EMSCRIPTEN_LOG_METHODDEF
#endif /* !defined(OS__EMSCRIPTEN_LOG_METHODDEF) */
-/*[clinic end generated code: output=89c21e2151ac7316 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=e709b8b783fbc261 input=a9049054013a1b77]*/
PyObject *setsigdef, PyObject *scheduler,
posix_spawnattr_t *attrp)
{
+ assert(scheduler == NULL || scheduler == Py_None || PyTuple_Check(scheduler));
long all_flags = 0;
errno = posix_spawnattr_init(attrp);
return -1;
}
- if (setpgroup) {
+ if (setpgroup && setpgroup != Py_None) {
pid_t pgid = PyLong_AsPid(setpgroup);
if (pgid == (pid_t)-1 && PyErr_Occurred()) {
goto fail;
}
#endif
- if (scheduler) {
+ if (scheduler && scheduler != Py_None) {
#ifdef POSIX_SPAWN_SETSCHEDULER
PyObject *py_schedpolicy;
PyObject *schedparam_obj;
goto exit;
}
+ if (scheduler && !PyTuple_Check(scheduler) && scheduler != Py_None) {
+ PyErr_Format(PyExc_TypeError,
+ "%s: scheduler must be a tuple or None", func_name);
+ goto exit;
+ }
+
argvlist = parse_arglist(argv, &argc);
if (argvlist == NULL) {
goto exit;
*
file_actions: object(c_default='NULL') = ()
A sequence of file action tuples.
- setpgroup: object = NULL
+ setpgroup: object(c_default='NULL') = None
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
resetids: bool = False
If the value is `true` the POSIX_SPAWN_RESETIDS will be activated.
The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
setsigdef: object(c_default='NULL') = ()
The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
- scheduler: object = NULL
+ scheduler: object(c_default='NULL') = None
A tuple with the scheduler policy (optional) and parameters.
Execute the program specified by path in a new process.
PyObject *setpgroup, int resetids, int setsid,
PyObject *setsigmask, PyObject *setsigdef,
PyObject *scheduler)
-/*[clinic end generated code: output=14a1098c566bc675 input=808aed1090d84e33]*/
+/*[clinic end generated code: output=14a1098c566bc675 input=69e7c9ebbdcf94a5]*/
{
return py_posix_spawn(0, module, path, argv, env, file_actions,
setpgroup, resetids, setsid, setsigmask, setsigdef,
*
file_actions: object(c_default='NULL') = ()
A sequence of file action tuples.
- setpgroup: object = NULL
+ setpgroup: object(c_default='NULL') = None
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
resetids: bool = False
If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
The sigmask to use with the POSIX_SPAWN_SETSIGMASK flag.
setsigdef: object(c_default='NULL') = ()
The sigmask to use with the POSIX_SPAWN_SETSIGDEF flag.
- scheduler: object = NULL
+ scheduler: object(c_default='NULL') = None
A tuple with the scheduler policy (optional) and parameters.
Execute the program specified by path in a new process.
PyObject *setpgroup, int resetids, int setsid,
PyObject *setsigmask, PyObject *setsigdef,
PyObject *scheduler)
-/*[clinic end generated code: output=7b9aaefe3031238d input=9e89e616116752a1]*/
+/*[clinic end generated code: output=7b9aaefe3031238d input=a5c057527c6881a5]*/
{
return py_posix_spawn(1, module, path, argv, env, file_actions,
setpgroup, resetids, setsid, setsigmask, setsigdef,