Skip to content
25 changes: 22 additions & 3 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -5179,7 +5179,8 @@ enum posix_spawn_file_actions_identifier {

static int
parse_file_actions(PyObject *file_actions,
posix_spawn_file_actions_t *file_actionsp)
posix_spawn_file_actions_t *file_actionsp,
PyObject *temp_buffer)
{
PyObject *seq;
PyObject *file_action = NULL;
Expand Down Expand Up @@ -5224,9 +5225,13 @@ parse_file_actions(PyObject *file_actions,
{
goto fail;
}
if (PyList_Append(temp_buffer, path)) {
Py_DECREF(path);
goto fail;
}
errno = posix_spawn_file_actions_addopen(file_actionsp,
fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode);
Py_DECREF(path); /* addopen copied it. */
Py_DECREF(path);
if (errno) {
posix_error();
goto fail;
Expand Down Expand Up @@ -5309,6 +5314,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
posix_spawn_file_actions_t *file_actionsp = NULL;
Py_ssize_t argc, envc;
PyObject *result = NULL;
PyObject *temp_buffer = NULL;
pid_t pid;
int err_code;

Expand Down Expand Up @@ -5349,7 +5355,19 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
}

if (file_actions != Py_None) {
if (parse_file_actions(file_actions, &file_actions_buf)) {
/* There is a bug in old versions of glibc that makes some of the
* helper functions for manipulating file actions not copy the provided
* buffers. The problem is that posix_spawn_file_actions_addopen does not
* copy the value of path for some old versions of glibc (<2.20).
* The use of temp_buffer here is a workaround that keeps the
* python objects that own the buffers alive until posix_spawn gets called.
* Check https://bugs.python.org/issue33630 and
* https://sourceware.org/bugzilla/show_bug.cgi?id=17048 for more info.*/
temp_buffer = PyList_New(0);
if (!temp_buffer) {
goto exit;
}
if (parse_file_actions(file_actions, &file_actions_buf, temp_buffer)) {
goto exit;
}
file_actionsp = &file_actions_buf;
Expand All @@ -5376,6 +5394,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv,
if (argvlist) {
free_string_array(argvlist, argc);
}
Py_XDECREF(temp_buffer);
return result;
}
#endif /* HAVE_POSIX_SPAWN */
Expand Down