bpo-20104: Add flag capabilities to posix_spawn (GH-6693)

Implement the "attributes objects" parameter of `os.posix_spawn` to complete the implementation and fully cover the underlying API.
This commit is contained in:
Pablo Galindo 2018-09-07 16:44:24 +01:00 committed by GitHub
parent 5e922658fb
commit 254a4663d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 344 additions and 14 deletions

View file

@ -5177,6 +5177,114 @@ enum posix_spawn_file_actions_identifier {
POSIX_SPAWN_DUP2
};
static int
convert_sched_param(PyObject *param, struct sched_param *res);
static int
parse_posix_spawn_flags(PyObject *setpgroup, int resetids, PyObject *setsigmask,
PyObject *setsigdef, PyObject *scheduler,
posix_spawnattr_t *attrp)
{
long all_flags = 0;
errno = posix_spawnattr_init(attrp);
if (errno) {
posix_error();
return -1;
}
if (setpgroup) {
pid_t pgid = PyLong_AsPid(setpgroup);
if (pgid == (pid_t)-1 && PyErr_Occurred()) {
goto fail;
}
errno = posix_spawnattr_setpgroup(attrp, pgid);
if (errno) {
posix_error();
goto fail;
}
all_flags |= POSIX_SPAWN_SETPGROUP;
}
if (resetids) {
all_flags |= POSIX_SPAWN_RESETIDS;
}
if (setsigmask) {
sigset_t set;
if (!_Py_Sigset_Converter(setsigmask, &set)) {
goto fail;
}
errno = posix_spawnattr_setsigmask(attrp, &set);
if (errno) {
posix_error();
goto fail;
}
all_flags |= POSIX_SPAWN_SETSIGMASK;
}
if (setsigdef) {
sigset_t set;
if (!_Py_Sigset_Converter(setsigdef, &set)) {
goto fail;
}
errno = posix_spawnattr_setsigdefault(attrp, &set);
if (errno) {
posix_error();
goto fail;
}
all_flags |= POSIX_SPAWN_SETSIGDEF;
}
if (scheduler) {
#ifdef POSIX_SPAWN_SETSCHEDULER
PyObject *py_schedpolicy;
struct sched_param schedparam;
if (!PyArg_ParseTuple(scheduler, "OO&"
";A scheduler tuple must have two elements",
&py_schedpolicy, convert_sched_param, &schedparam)) {
goto fail;
}
if (py_schedpolicy != Py_None) {
int schedpolicy = _PyLong_AsInt(py_schedpolicy);
if (schedpolicy == -1 && PyErr_Occurred()) {
goto fail;
}
errno = posix_spawnattr_setschedpolicy(attrp, schedpolicy);
if (errno) {
posix_error();
goto fail;
}
all_flags |= POSIX_SPAWN_SETSCHEDULER;
}
errno = posix_spawnattr_setschedparam(attrp, &schedparam);
if (errno) {
posix_error();
goto fail;
}
all_flags |= POSIX_SPAWN_SETSCHEDPARAM;
#else
PyErr_SetString(PyExc_NotImplementedError,
"The scheduler option is not supported in this system.");
goto fail;
#endif
}
errno = posix_spawnattr_setflags(attrp, all_flags);
if (errno) {
posix_error();
goto fail;
}
return 0;
fail:
(void)posix_spawnattr_destroy(attrp);
return -1;
}
static int
parse_file_actions(PyObject *file_actions,
posix_spawn_file_actions_t *file_actionsp,
@ -5277,6 +5385,7 @@ parse_file_actions(PyObject *file_actions,
}
Py_DECREF(file_action);
}
Py_DECREF(seq);
return 0;
@ -5299,19 +5408,33 @@ os.posix_spawn
file_actions: object = None
A sequence of file action tuples.
/
*
setpgroup: object = NULL
The pgroup to use with the POSIX_SPAWN_SETPGROUP flag.
resetids: bool(accept={int}) = False
If the value is `True` the POSIX_SPAWN_RESETIDS will be activated.
setsigmask: object(c_default='NULL') = ()
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
A tuple with the scheduler policy (optional) and parameters.
Execute the program specified by path in a new process.
[clinic start generated code]*/
static PyObject *
os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
PyObject *env, PyObject *file_actions)
/*[clinic end generated code: output=d023521f541c709c input=a3db1021d33230dc]*/
PyObject *env, PyObject *file_actions,
PyObject *setpgroup, int resetids, PyObject *setsigmask,
PyObject *setsigdef, PyObject *scheduler)
/*[clinic end generated code: output=45dfa4c515d09f2c input=2d7a7578430a90f0]*/
{
EXECV_CHAR **argvlist = NULL;
EXECV_CHAR **envlist = NULL;
posix_spawn_file_actions_t file_actions_buf;
posix_spawn_file_actions_t *file_actionsp = NULL;
posix_spawnattr_t attr;
posix_spawnattr_t *attrp = NULL;
Py_ssize_t argc, envc;
PyObject *result = NULL;
PyObject *temp_buffer = NULL;
@ -5373,9 +5496,15 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
file_actionsp = &file_actions_buf;
}
if (parse_posix_spawn_flags(setpgroup, resetids, setsigmask,
setsigdef, scheduler, &attr)) {
goto exit;
}
attrp = &attr;
_Py_BEGIN_SUPPRESS_IPH
err_code = posix_spawn(&pid, path->narrow,
file_actionsp, NULL, argvlist, envlist);
file_actionsp, attrp, argvlist, envlist);
_Py_END_SUPPRESS_IPH
if (err_code) {
errno = err_code;
@ -5388,6 +5517,9 @@ exit:
if (file_actionsp) {
(void)posix_spawn_file_actions_destroy(file_actionsp);
}
if (attrp) {
(void)posix_spawnattr_destroy(attrp);
}
if (envlist) {
free_string_array(envlist, envc);
}