diff options
Diffstat (limited to 'contrib/tools/python3/Modules/_posixsubprocess.c')
| -rw-r--r-- | contrib/tools/python3/Modules/_posixsubprocess.c | 130 |
1 files changed, 111 insertions, 19 deletions
diff --git a/contrib/tools/python3/Modules/_posixsubprocess.c b/contrib/tools/python3/Modules/_posixsubprocess.c index 35ea2ac306a..0a7ef74e26f 100644 --- a/contrib/tools/python3/Modules/_posixsubprocess.c +++ b/contrib/tools/python3/Modules/_posixsubprocess.c @@ -6,29 +6,30 @@ #include "Python.h" #include "pycore_fileutils.h" #include "pycore_pystate.h" +#include "pycore_signal.h" // _Py_RestoreSignals() #if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE) -# define _GNU_SOURCE +# define _GNU_SOURCE #endif -#include <unistd.h> -#include <fcntl.h> +#include <unistd.h> // close() +#include <fcntl.h> // fcntl() #ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> +# include <sys/types.h> #endif #if defined(HAVE_SYS_STAT_H) -#include <sys/stat.h> +# include <sys/stat.h> // stat() #endif #ifdef HAVE_SYS_SYSCALL_H -#include <sys/syscall.h> +# include <sys/syscall.h> #endif #if defined(HAVE_SYS_RESOURCE_H) -#include <sys/resource.h> +# include <sys/resource.h> #endif #ifdef HAVE_DIRENT_H -#include <dirent.h> +# include <dirent.h> // opendir() +#endif +#if defined(HAVE_SETGROUPS) +# include <grp.h> // setgroups() #endif -#ifdef HAVE_GRP_H -#include <grp.h> -#endif /* HAVE_GRP_H */ #include "posixmodule.h" @@ -86,15 +87,16 @@ class pid_t_converter(CConverter): type = 'pid_t' format_unit = '" _Py_PARSE_PID "' - def parse_arg(self, argname, displayname): - return """ + def parse_arg(self, argname, displayname, *, limited_capi): + return self.format_code(""" {paramname} = PyLong_AsPid({argname}); if ({paramname} == -1 && PyErr_Occurred()) {{{{ goto exit; }}}} - """.format(argname=argname, paramname=self.parser_name) + """, + argname=argname) [python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=5af1c116d56cbb5a]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=c94349aa1aad151d]*/ #include "clinic/_posixsubprocess.c.h" @@ -182,6 +184,88 @@ _is_fd_in_sorted_fd_sequence(int fd, int *fd_sequence, return 0; } + +// Forward declaration +static void _Py_FreeCharPArray(char *const array[]); + +/* + * Flatten a sequence of bytes() objects into a C array of + * NULL terminated string pointers with a NULL char* terminating the array. + * (ie: an argv or env list) + * + * Memory allocated for the returned list is allocated using PyMem_Malloc() + * and MUST be freed by _Py_FreeCharPArray(). + */ +static char *const * +_PySequence_BytesToCharpArray(PyObject* self) +{ + char **array; + Py_ssize_t i, argc; + PyObject *item = NULL; + Py_ssize_t size; + + argc = PySequence_Size(self); + if (argc == -1) + return NULL; + + assert(argc >= 0); + + if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) { + PyErr_NoMemory(); + return NULL; + } + + array = PyMem_Malloc((argc + 1) * sizeof(char *)); + if (array == NULL) { + PyErr_NoMemory(); + return NULL; + } + for (i = 0; i < argc; ++i) { + char *data; + item = PySequence_GetItem(self, i); + if (item == NULL) { + /* NULL terminate before freeing. */ + array[i] = NULL; + goto fail; + } + /* check for embedded null bytes */ + if (PyBytes_AsStringAndSize(item, &data, NULL) < 0) { + /* NULL terminate before freeing. */ + array[i] = NULL; + goto fail; + } + size = PyBytes_GET_SIZE(item) + 1; + array[i] = PyMem_Malloc(size); + if (!array[i]) { + PyErr_NoMemory(); + goto fail; + } + memcpy(array[i], data, size); + Py_DECREF(item); + } + array[argc] = NULL; + + return array; + +fail: + Py_XDECREF(item); + _Py_FreeCharPArray(array); + return NULL; +} + + +/* Free's a NULL terminated char** array of C strings. */ +static void +_Py_FreeCharPArray(char *const array[]) +{ + Py_ssize_t i; + for (i = 0; array[i] != NULL; ++i) { + PyMem_Free(array[i]); + } + PyMem_Free((void*)array); +} + + /* * Do all the Python C API calls in the parent process to turn the pass_fds * "py_fds_to_keep" tuple into a C array. The caller owns allocation and @@ -428,7 +512,13 @@ _close_open_fds_maybe_unsafe(int start_fd, int *fds_to_keep, proc_fd_dir = NULL; else #endif +#if defined(_AIX) + char fd_path[PATH_MAX]; + snprintf(fd_path, sizeof(fd_path), "/proc/%ld/fd", (long)getpid()); + proc_fd_dir = opendir(fd_path); +#else proc_fd_dir = opendir(FD_DIR); +#endif if (!proc_fd_dir) { /* No way to get a list of open fds. */ _close_range_except(start_fd, -1, fds_to_keep, fds_to_keep_len, @@ -544,7 +634,7 @@ reset_signal_handlers(const sigset_t *child_sigmask) * (v)fork to set things up and call exec(). * * All of the code in this function must only use async-signal-safe functions, - * listed at `man 7 signal` or + * listed at `man 7 signal-safety` or * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. * * This restriction is documented at @@ -662,8 +752,9 @@ child_exec(char *const exec_array[], if (child_umask >= 0) umask(child_umask); /* umask() always succeeds. */ - if (restore_signals) + if (restore_signals) { _Py_RestoreSignals(); + } #ifdef VFORK_USABLE if (child_sigmask) { @@ -945,11 +1036,11 @@ subprocess_fork_exec_impl(PyObject *module, PyObject *process_args, int *c_fds_to_keep = NULL; Py_ssize_t fds_to_keep_len = PyTuple_GET_SIZE(py_fds_to_keep); - PyInterpreterState *interp = PyInterpreterState_Get(); + PyInterpreterState *interp = _PyInterpreterState_GET(); if ((preexec_fn != Py_None) && _PyInterpreterState_GetFinalizing(interp) != NULL) { - PyErr_SetString(PyExc_RuntimeError, + PyErr_SetString(PyExc_PythonFinalizationError, "preexec_fn not supported at interpreter shutdown"); return NULL; } @@ -1232,6 +1323,7 @@ static PyMethodDef module_methods[] = { static PyModuleDef_Slot _posixsubprocess_slots[] = { {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} }; |
