From f138f0a0ef3175ac2e250ec2a6c0d97c5745affc Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Sat, 6 Jan 2018 01:13:26 +0000 Subject: [PATCH 1/8] Expose posix_spawn in os module --- Lib/os.py | 45 ++++++++++ Lib/test/test_posix.py | 15 ++++ Modules/clinic/posixmodule.c.h | 87 ++++++++++++++++++- Modules/posixmodule.c | 154 ++++++++++++++++++++++++++++++++- 4 files changed, 299 insertions(+), 2 deletions(-) diff --git a/Lib/os.py b/Lib/os.py index 499e6285618f21..2a584832a08102 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -1076,3 +1076,48 @@ def __fspath__(self): @classmethod def __subclasshook__(cls, subclass): return hasattr(subclass, '__fspath__') + +class FileActions(object): + def __init__(self): + self.open_action = None + self.close_action = None + self.dup2_action = None + + def add_open(self, fd, path, oflag, mode): + if not isinstance(fd, int): + raise TypeError( + "fd must be an int not {0}.".format(type(fd).__name__)) + + if not isinstance(path, str): + raise TypeError( + "path must be bytes not {0}.".format(type(path).__name__)) + + if not isinstance(oflag, int): + raise TypeError( + "oflag must be an int not {0}.".format(type(oflag.__name__))) + + if not isinstance(mode, int): + raise TypeError( + "mode must be int not {0}.".format(type(mode).__name__)) + + self.open_action = (fd, path.encode(), oflag, mode) + + def add_close(self, fd): + if not isinstance(fd, int): + raise TypeError( + "fd must be an int not {0}.".format(type(fd).__name__)) + + self.close_action = (fd,) + + + def add_dup2(self, fd, new_fd): + if not isinstance(fd, int): + raise TypeError( + "fd must be an int not {0}.".format(type(fd).__name__)) + + if not isinstance(new_fd, int): + raise TypeError( + "new_fd must be an int not {0}.".format(type(new_fd).__name__)) + + self.dup2_action = (fd, new_fd) + diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index a7f3d34f66db9f..384d805ca81c90 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -176,6 +176,21 @@ def test_fexecve(self): finally: os.close(fp) + + def test_posix_spawn(self): + pid = posix.posixspawn(sys.executable, [sys.executable, "-c", "pass"], os.environ) + self.assertEqual(os.waitpid(pid,0),(pid,0)) + + def test_posix_spawn_file_actions(self): + file_actions = os.FileActions() + file_actions.add_open(3,os.path.realpath(__file__),0,0) + file_actions.add_close(2) + file_actions.add_dup2(1,4) + pid = posix.posixspawn(sys.executable, [sys.executable, "-c", "pass"], os.environ, file_actions) + self.assertEqual(os.waitpid(pid,0),(pid,0)) + + + @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()") @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") def test_waitid(self): diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index f432437e99efe1..673d04482f8661 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1721,6 +1721,87 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #endif /* defined(HAVE_EXECV) */ +PyDoc_STRVAR(os_blech__doc__, +"blech($module, /, mode)\n" +"--\n" +"\n" +"Obtain the blech\n" +"\n" +" mode\n" +" Mode of process creation."); + +#define OS_BLECH_METHODDEF \ + {"blech", (PyCFunction)os_blech, METH_FASTCALL|METH_KEYWORDS, os_blech__doc__}, + +static PyObject * +os_blech_impl(PyObject *module, int mode); + +static PyObject * +os_blech(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"mode", NULL}; + static _PyArg_Parser _parser = {"i:blech", _keywords, 0}; + int mode; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &mode)) { + goto exit; + } + return_value = os_blech_impl(module, mode); + +exit: + return return_value; +} + +#if defined(HAVE_POSIXSPAWN) + +PyDoc_STRVAR(os_posixspawn__doc__, +"posixspawn($module, path, argv, env, file_actions=None, /)\n" +"--\n" +"\n" +"Execute the program specified by path in a new process.\n" +"\n" +" path\n" +" Path of executable file.\n" +" argv\n" +" Tuple or list of strings.\n" +" env\n" +" Dictionary of strings mapping to strings.\n" +" file_actions\n" +" FileActions object."); + +#define OS_POSIXSPAWN_METHODDEF \ + {"posixspawn", (PyCFunction)os_posixspawn, METH_FASTCALL, os_posixspawn__doc__}, + +static PyObject * +os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions); + +static PyObject * +os_posixspawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + path_t path = PATH_T_INITIALIZE("posixspawn", "path", 0, 0); + PyObject *argv; + PyObject *env; + PyObject *file_actions = Py_None; + + if (!_PyArg_ParseStack(args, nargs, "O&OO|O:posixspawn", + path_converter, &path, &argv, &env, &file_actions)) { + goto exit; + } + return_value = os_posixspawn_impl(module, &path, argv, env, file_actions); + +exit: + /* Cleanup for path */ + path_cleanup(&path); + + return return_value; +} + +#endif /* defined(HAVE_POSIXSPAWN) */ + #if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) PyDoc_STRVAR(os_spawnv__doc__, @@ -6137,6 +6218,10 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #define OS_EXECVE_METHODDEF #endif /* !defined(OS_EXECVE_METHODDEF) */ +#ifndef OS_POSIXSPAWN_METHODDEF + #define OS_POSIXSPAWN_METHODDEF +#endif /* !defined(OS_POSIXSPAWN_METHODDEF) */ + #ifndef OS_SPAWNV_METHODDEF #define OS_SPAWNV_METHODDEF #endif /* !defined(OS_SPAWNV_METHODDEF) */ @@ -6528,4 +6613,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=06ace805893aa10c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=cbd18f7a5d3c1d09 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index ceea85559c85ed..f29aa909b03cc6 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -176,6 +176,7 @@ corresponding Unix manual entries for more information on calls."); #else /* Unix functions that the configure script doesn't check for */ #define HAVE_EXECV 1 +#define HAVE_POSIXSPAWN 1 #define HAVE_FORK 1 #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ #define HAVE_FORK1 1 @@ -246,6 +247,10 @@ extern int lstat(const char *, struct stat *); #endif /* !_MSC_VER */ +#ifdef HAVE_POSIXSPAWN +#include +#endif + #ifdef HAVE_UTIME_H #include #endif /* HAVE_UTIME_H */ @@ -5097,6 +5102,152 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) #endif /* HAVE_EXECV */ +/*[clinic input] +os.blech + + mode: int + Mode of process creation. + +Obtain the blech +[clinic start generated code]*/ + +static PyObject * +os_blech_impl(PyObject *module, int mode) +/*[clinic end generated code: output=62ed91ef21700cfc input=0c4595b146d42476]*/ +{ + return PyLong_FromLong(mode); +} + +static void reprint(PyObject *obj) { + PyObject* repr = PyObject_Repr(obj); + PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~"); + const char *bytes = PyBytes_AS_STRING(str); + + printf("REPR: %s\n", bytes); + + Py_XDECREF(repr); + Py_XDECREF(str); +} + +#ifdef HAVE_POSIXSPAWN +/*[clinic input] +os.posixspawn + path: path_t + Path of executable file. + argv: object + Tuple or list of strings. + env: object + Dictionary of strings mapping to strings. + file_actions: object = None + FileActions object. + / + +Execute the program specified by path in a new process. +[clinic start generated code]*/ + +static PyObject * +os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions) +/*[clinic end generated code: output=62379d0eb449d090 input=6b434e4240ef3050]*/ +{ + + EXECV_CHAR **argvlist = NULL; + EXECV_CHAR **envlist; + Py_ssize_t argc, envc; + + /* posix_spawn has three arguments: (path, argv, env), where + argv is a list or tuple of strings and env is a dictionary + like posix.environ. */ + + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + PyErr_SetString(PyExc_TypeError, + "posix_spawn: argv must be a tuple or list"); + goto fail; + } + argc = PySequence_Size(argv); + if (argc < 1) { + PyErr_SetString(PyExc_ValueError, "posix_spawn: argv must not be empty"); + return NULL; + } + + if (!PyMapping_Check(env)) { + PyErr_SetString(PyExc_TypeError, + "posix_spawn: environment must be a mapping object"); + goto fail; + } + + argvlist = parse_arglist(argv, &argc); + if (argvlist == NULL) { + goto fail; + } + if (!argvlist[0][0]) { + PyErr_SetString(PyExc_ValueError, + "posix_spawn: argv first element cannot be empty"); + goto fail; + } + + envlist = parse_envlist(env, &envc); + if (envlist == NULL) + goto fail; + + pid_t pid; + posix_spawn_file_actions_t *file_actionsp = NULL; + if (file_actions != NULL && file_actions != Py_None){ + posix_spawn_file_actions_t _file_actions; + if(posix_spawn_file_actions_init(&_file_actions) != 0){ + PyErr_SetString(PyExc_TypeError, + "Error initializing file actions"); + goto fail; + } + + + file_actionsp = &_file_actions; + + PyObject* open_action = PyObject_GetAttrString(file_actions, "open_action"); + if (open_action != Py_None){ + long open_fd = PyLong_AsLong(PyTuple_GetItem(open_action, 0)); + char* open_path = PyBytes_AsString(PyTuple_GetItem(open_action, 1)); + long open_oflag = PyLong_AsLong(PyTuple_GetItem(open_action, 2)); + long open_mode = PyLong_AsLong(PyTuple_GetItem(open_action, 3)); + posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode); + } + + PyObject* close_action = PyObject_GetAttrString(file_actions, "close_action"); + if (close_action != Py_None){ + long close_fd = PyLong_AsLong(PyTuple_GetItem(close_action, 0)); + posix_spawn_file_actions_addclose(file_actionsp, close_fd); + } + + PyObject* dup2_action = PyObject_GetAttrString(file_actions, "dup2_action"); + if (dup2_action != Py_None){ + long fd1 = PyLong_AsLong(PyTuple_GetItem(dup2_action, 0)); + long fd2 = PyLong_AsLong(PyTuple_GetItem(dup2_action, 1)); + posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2); + } + + } + + + + _Py_BEGIN_SUPPRESS_IPH + posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); + return PyLong_FromPid(pid); + _Py_END_SUPPRESS_IPH + + /* If we get here it's definitely an error */ + + path_error(path); + + free_string_array(envlist, envc); + fail: + if (argvlist) + free_string_array(argvlist, argc); + return NULL; + + +} +#endif + #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) /*[clinic input] @@ -5189,7 +5340,6 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); } - /*[clinic input] os.spawnve @@ -12610,6 +12760,8 @@ static PyMethodDef posix_methods[] = { OS_NICE_METHODDEF OS_GETPRIORITY_METHODDEF OS_SETPRIORITY_METHODDEF + OS_BLECH_METHODDEF + OS_POSIXSPAWN_METHODDEF #ifdef HAVE_READLINK {"readlink", (PyCFunction)posix_readlink, METH_VARARGS | METH_KEYWORDS, From bd39bce77cf386a53b73bdc3c7e24f4e600ec6e8 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Sat, 6 Jan 2018 01:15:05 +0000 Subject: [PATCH 2/8] Add News entry --- .../Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst b/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst new file mode 100644 index 00000000000000..bc9a089902de1f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst @@ -0,0 +1,2 @@ +Expose posix_spawn and a FileActions object to work with said function in +the os module. From e8ca1d4d5745c795d7cc12d3d3b78411f86abc1a Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Sat, 6 Jan 2018 01:23:19 +0000 Subject: [PATCH 3/8] Update argument clinic files --- Lib/os.py | 14 ++++++------- Modules/clinic/posixmodule.c.h | 35 +-------------------------------- Modules/posixmodule.c | 36 +++------------------------------- 3 files changed, 10 insertions(+), 75 deletions(-) diff --git a/Lib/os.py b/Lib/os.py index 2a584832a08102..5d88d31594875f 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -1079,9 +1079,9 @@ def __subclasshook__(cls, subclass): class FileActions(object): def __init__(self): - self.open_action = None - self.close_action = None - self.dup2_action = None + self._open_action = None + self._close_action = None + self._dup2_action = None def add_open(self, fd, path, oflag, mode): if not isinstance(fd, int): @@ -1100,15 +1100,14 @@ def add_open(self, fd, path, oflag, mode): raise TypeError( "mode must be int not {0}.".format(type(mode).__name__)) - self.open_action = (fd, path.encode(), oflag, mode) + self._open_action = (fd, path.encode(), oflag, mode) def add_close(self, fd): if not isinstance(fd, int): raise TypeError( "fd must be an int not {0}.".format(type(fd).__name__)) - self.close_action = (fd,) - + self._close_action = (fd,) def add_dup2(self, fd, new_fd): if not isinstance(fd, int): @@ -1119,5 +1118,4 @@ def add_dup2(self, fd, new_fd): raise TypeError( "new_fd must be an int not {0}.".format(type(new_fd).__name__)) - self.dup2_action = (fd, new_fd) - + self._dup2_action = (fd, new_fd) diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 673d04482f8661..adc97e9ba1cb8c 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1721,39 +1721,6 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #endif /* defined(HAVE_EXECV) */ -PyDoc_STRVAR(os_blech__doc__, -"blech($module, /, mode)\n" -"--\n" -"\n" -"Obtain the blech\n" -"\n" -" mode\n" -" Mode of process creation."); - -#define OS_BLECH_METHODDEF \ - {"blech", (PyCFunction)os_blech, METH_FASTCALL|METH_KEYWORDS, os_blech__doc__}, - -static PyObject * -os_blech_impl(PyObject *module, int mode); - -static PyObject * -os_blech(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) -{ - PyObject *return_value = NULL; - static const char * const _keywords[] = {"mode", NULL}; - static _PyArg_Parser _parser = {"i:blech", _keywords, 0}; - int mode; - - if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &mode)) { - goto exit; - } - return_value = os_blech_impl(module, mode); - -exit: - return return_value; -} - #if defined(HAVE_POSIXSPAWN) PyDoc_STRVAR(os_posixspawn__doc__, @@ -6613,4 +6580,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=cbd18f7a5d3c1d09 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2337d5dd34318f86 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index f29aa909b03cc6..90199b49601d76 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5102,33 +5102,6 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) #endif /* HAVE_EXECV */ -/*[clinic input] -os.blech - - mode: int - Mode of process creation. - -Obtain the blech -[clinic start generated code]*/ - -static PyObject * -os_blech_impl(PyObject *module, int mode) -/*[clinic end generated code: output=62ed91ef21700cfc input=0c4595b146d42476]*/ -{ - return PyLong_FromLong(mode); -} - -static void reprint(PyObject *obj) { - PyObject* repr = PyObject_Repr(obj); - PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "~E~"); - const char *bytes = PyBytes_AS_STRING(str); - - printf("REPR: %s\n", bytes); - - Py_XDECREF(repr); - Py_XDECREF(str); -} - #ifdef HAVE_POSIXSPAWN /*[clinic input] os.posixspawn @@ -5203,7 +5176,7 @@ os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, file_actionsp = &_file_actions; - PyObject* open_action = PyObject_GetAttrString(file_actions, "open_action"); + PyObject* open_action = PyObject_GetAttrString(file_actions, "_open_action"); if (open_action != Py_None){ long open_fd = PyLong_AsLong(PyTuple_GetItem(open_action, 0)); char* open_path = PyBytes_AsString(PyTuple_GetItem(open_action, 1)); @@ -5212,13 +5185,13 @@ os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode); } - PyObject* close_action = PyObject_GetAttrString(file_actions, "close_action"); + PyObject* close_action = PyObject_GetAttrString(file_actions, "_close_action"); if (close_action != Py_None){ long close_fd = PyLong_AsLong(PyTuple_GetItem(close_action, 0)); posix_spawn_file_actions_addclose(file_actionsp, close_fd); } - PyObject* dup2_action = PyObject_GetAttrString(file_actions, "dup2_action"); + PyObject* dup2_action = PyObject_GetAttrString(file_actions, "_dup2_action"); if (dup2_action != Py_None){ long fd1 = PyLong_AsLong(PyTuple_GetItem(dup2_action, 0)); long fd2 = PyLong_AsLong(PyTuple_GetItem(dup2_action, 1)); @@ -5234,8 +5207,6 @@ os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, return PyLong_FromPid(pid); _Py_END_SUPPRESS_IPH - /* If we get here it's definitely an error */ - path_error(path); free_string_array(envlist, envc); @@ -12760,7 +12731,6 @@ static PyMethodDef posix_methods[] = { OS_NICE_METHODDEF OS_GETPRIORITY_METHODDEF OS_SETPRIORITY_METHODDEF - OS_BLECH_METHODDEF OS_POSIXSPAWN_METHODDEF #ifdef HAVE_READLINK {"readlink", (PyCFunction)posix_readlink, From 7ea83ede26f66a327cd2704d49a7df0221138199 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 10 Jan 2018 22:37:59 +0000 Subject: [PATCH 4/8] Adapt posix_spawn API to pythonic posix compatible version --- @test_11613_tmp | 0 @test_1931_tmp | 0 @test_20400_tmp | 0 @test_22339_tmp | 0 @test_24611_tmp | 0 @test_24744_tmp | 0 @test_24872_tmp | 0 @test_25176_tmp | 0 @test_25627_tmp | 0 @test_25914_tmp | 0 @test_26145_tmp | 0 @test_26441_tmp | 0 @test_26725_tmp | 0 @test_26954_tmp | 0 @test_27185_tmp | 0 @test_27415_tmp | 0 @test_27645_tmp | 0 @test_28387_tmp | 0 @test_29448_tmp | 0 @test_29799_tmp | 0 @test_30178_tmp | 0 @test_30414_tmp | 0 @test_30664_tmp | 0 @test_30905_tmp | 0 @test_31032_tmp | 0 @test_31180_tmp | 0 @test_31348_tmp | 0 @test_31581_tmp | 0 @test_31814_tmp | 0 @test_32141_tmp | 0 @test_32372_tmp | 0 @test_32651_tmp | 0 @test_3753_tmp | 0 @test_9809_tmp | 0 Lib/os.py | 43 ----------- Lib/test/test_posix.py | 16 ++-- Modules/clinic/posixmodule.c.h | 32 ++++---- Modules/posixmodule.c | 135 +++++++++++++++++++++++---------- 38 files changed, 120 insertions(+), 106 deletions(-) create mode 100644 @test_11613_tmp create mode 100644 @test_1931_tmp create mode 100644 @test_20400_tmp create mode 100644 @test_22339_tmp create mode 100644 @test_24611_tmp create mode 100644 @test_24744_tmp create mode 100644 @test_24872_tmp create mode 100644 @test_25176_tmp create mode 100644 @test_25627_tmp create mode 100644 @test_25914_tmp create mode 100644 @test_26145_tmp create mode 100644 @test_26441_tmp create mode 100644 @test_26725_tmp create mode 100644 @test_26954_tmp create mode 100644 @test_27185_tmp create mode 100644 @test_27415_tmp create mode 100644 @test_27645_tmp create mode 100644 @test_28387_tmp create mode 100644 @test_29448_tmp create mode 100644 @test_29799_tmp create mode 100644 @test_30178_tmp create mode 100644 @test_30414_tmp create mode 100644 @test_30664_tmp create mode 100644 @test_30905_tmp create mode 100644 @test_31032_tmp create mode 100644 @test_31180_tmp create mode 100644 @test_31348_tmp create mode 100644 @test_31581_tmp create mode 100644 @test_31814_tmp create mode 100644 @test_32141_tmp create mode 100644 @test_32372_tmp create mode 100644 @test_32651_tmp create mode 100644 @test_3753_tmp create mode 100644 @test_9809_tmp diff --git a/@test_11613_tmp b/@test_11613_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_1931_tmp b/@test_1931_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_20400_tmp b/@test_20400_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_22339_tmp b/@test_22339_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_24611_tmp b/@test_24611_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_24744_tmp b/@test_24744_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_24872_tmp b/@test_24872_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_25176_tmp b/@test_25176_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_25627_tmp b/@test_25627_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_25914_tmp b/@test_25914_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_26145_tmp b/@test_26145_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_26441_tmp b/@test_26441_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_26725_tmp b/@test_26725_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_26954_tmp b/@test_26954_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_27185_tmp b/@test_27185_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_27415_tmp b/@test_27415_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_27645_tmp b/@test_27645_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_28387_tmp b/@test_28387_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_29448_tmp b/@test_29448_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_29799_tmp b/@test_29799_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_30178_tmp b/@test_30178_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_30414_tmp b/@test_30414_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_30664_tmp b/@test_30664_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_30905_tmp b/@test_30905_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_31032_tmp b/@test_31032_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_31180_tmp b/@test_31180_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_31348_tmp b/@test_31348_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_31581_tmp b/@test_31581_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_31814_tmp b/@test_31814_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_32141_tmp b/@test_32141_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_32372_tmp b/@test_32372_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_32651_tmp b/@test_32651_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_3753_tmp b/@test_3753_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/@test_9809_tmp b/@test_9809_tmp new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/Lib/os.py b/Lib/os.py index 5d88d31594875f..499e6285618f21 100644 --- a/Lib/os.py +++ b/Lib/os.py @@ -1076,46 +1076,3 @@ def __fspath__(self): @classmethod def __subclasshook__(cls, subclass): return hasattr(subclass, '__fspath__') - -class FileActions(object): - def __init__(self): - self._open_action = None - self._close_action = None - self._dup2_action = None - - def add_open(self, fd, path, oflag, mode): - if not isinstance(fd, int): - raise TypeError( - "fd must be an int not {0}.".format(type(fd).__name__)) - - if not isinstance(path, str): - raise TypeError( - "path must be bytes not {0}.".format(type(path).__name__)) - - if not isinstance(oflag, int): - raise TypeError( - "oflag must be an int not {0}.".format(type(oflag.__name__))) - - if not isinstance(mode, int): - raise TypeError( - "mode must be int not {0}.".format(type(mode).__name__)) - - self._open_action = (fd, path.encode(), oflag, mode) - - def add_close(self, fd): - if not isinstance(fd, int): - raise TypeError( - "fd must be an int not {0}.".format(type(fd).__name__)) - - self._close_action = (fd,) - - def add_dup2(self, fd, new_fd): - if not isinstance(fd, int): - raise TypeError( - "fd must be an int not {0}.".format(type(fd).__name__)) - - if not isinstance(new_fd, int): - raise TypeError( - "new_fd must be an int not {0}.".format(type(new_fd).__name__)) - - self._dup2_action = (fd, new_fd) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 384d805ca81c90..93b154947bff1c 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -177,20 +177,22 @@ def test_fexecve(self): os.close(fp) + @unittest.skipUnless(hasattr(os, 'posixspawn'), "test needs os.posix_spawn") def test_posix_spawn(self): - pid = posix.posixspawn(sys.executable, [sys.executable, "-c", "pass"], os.environ) + pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ,[]) self.assertEqual(os.waitpid(pid,0),(pid,0)) + + @unittest.skipUnless(hasattr(os, 'posixspawn'), "test needs os.posix_spawn") def test_posix_spawn_file_actions(self): - file_actions = os.FileActions() - file_actions.add_open(3,os.path.realpath(__file__),0,0) - file_actions.add_close(2) - file_actions.add_dup2(1,4) - pid = posix.posixspawn(sys.executable, [sys.executable, "-c", "pass"], os.environ, file_actions) + file_actions = [] + file_actions.append((0,3,os.path.realpath(__file__),0,0)) + file_actions.append((os.POSIX_SPAWN_CLOSE,2)) + file_actions.append((os.POSIX_SPAWN_DUP2,1,4)) + pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ, file_actions) self.assertEqual(os.waitpid(pid,0),(pid,0)) - @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()") @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") def test_waitid(self): diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index adc97e9ba1cb8c..d6af15ffc2cac3 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1721,10 +1721,10 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #endif /* defined(HAVE_EXECV) */ -#if defined(HAVE_POSIXSPAWN) +#if defined(HAVE_POSIX_SPAWN) -PyDoc_STRVAR(os_posixspawn__doc__, -"posixspawn($module, path, argv, env, file_actions=None, /)\n" +PyDoc_STRVAR(os_posix_spawn__doc__, +"posix_spawn($module, path, argv, env, file_actions=None, /)\n" "--\n" "\n" "Execute the program specified by path in a new process.\n" @@ -1738,27 +1738,27 @@ PyDoc_STRVAR(os_posixspawn__doc__, " file_actions\n" " FileActions object."); -#define OS_POSIXSPAWN_METHODDEF \ - {"posixspawn", (PyCFunction)os_posixspawn, METH_FASTCALL, os_posixspawn__doc__}, +#define OS_POSIX_SPAWN_METHODDEF \ + {"posix_spawn", (PyCFunction)os_posix_spawn, METH_FASTCALL, os_posix_spawn__doc__}, static PyObject * -os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions); +os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions); static PyObject * -os_posixspawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("posixspawn", "path", 0, 0); + path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); PyObject *argv; PyObject *env; PyObject *file_actions = Py_None; - if (!_PyArg_ParseStack(args, nargs, "O&OO|O:posixspawn", + if (!_PyArg_ParseStack(args, nargs, "O&OO|O:posix_spawn", path_converter, &path, &argv, &env, &file_actions)) { goto exit; } - return_value = os_posixspawn_impl(module, &path, argv, env, file_actions); + return_value = os_posix_spawn_impl(module, &path, argv, env, file_actions); exit: /* Cleanup for path */ @@ -1767,7 +1767,7 @@ os_posixspawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* defined(HAVE_POSIXSPAWN) */ +#endif /* defined(HAVE_POSIX_SPAWN) */ #if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) @@ -6185,9 +6185,9 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #define OS_EXECVE_METHODDEF #endif /* !defined(OS_EXECVE_METHODDEF) */ -#ifndef OS_POSIXSPAWN_METHODDEF - #define OS_POSIXSPAWN_METHODDEF -#endif /* !defined(OS_POSIXSPAWN_METHODDEF) */ +#ifndef OS_POSIX_SPAWN_METHODDEF + #define OS_POSIX_SPAWN_METHODDEF +#endif /* !defined(OS_POSIX_SPAWN_METHODDEF) */ #ifndef OS_SPAWNV_METHODDEF #define OS_SPAWNV_METHODDEF @@ -6580,4 +6580,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=2337d5dd34318f86 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8e5d4a01257b6292 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 90199b49601d76..dda27f44d6e130 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -176,7 +176,7 @@ corresponding Unix manual entries for more information on calls."); #else /* Unix functions that the configure script doesn't check for */ #define HAVE_EXECV 1 -#define HAVE_POSIXSPAWN 1 +#define HAVE_POSIX_SPAWN 1 #define HAVE_FORK 1 #if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ #define HAVE_FORK1 1 @@ -247,7 +247,7 @@ extern int lstat(const char *, struct stat *); #endif /* !_MSC_VER */ -#ifdef HAVE_POSIXSPAWN +#ifdef HAVE_POSIX_SPAWN #include #endif @@ -5102,9 +5102,17 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) #endif /* HAVE_EXECV */ -#ifdef HAVE_POSIXSPAWN +#ifdef HAVE_POSIX_SPAWN + +enum posix_spawn_file_actions_identifier { + POSIX_SPAWN_OPEN, + POSIX_SPAWN_CLOSE, + POSIX_SPAWN_DUP2 +}; + /*[clinic input] -os.posixspawn + +os.posix_spawn path: path_t Path of executable file. argv: object @@ -5119,20 +5127,19 @@ Execute the program specified by path in a new process. [clinic start generated code]*/ static PyObject * -os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions) -/*[clinic end generated code: output=62379d0eb449d090 input=6b434e4240ef3050]*/ +os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, + PyObject *env, PyObject *file_actions) +/*[clinic end generated code: output=d023521f541c709c input=0ec9f1cfdc890be5]*/ { - EXECV_CHAR **argvlist = NULL; EXECV_CHAR **envlist; Py_ssize_t argc, envc; /* posix_spawn has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary + argv is a list or tuple of strings and env is a dictionary like posix.environ. */ - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { + if (!PySequence_Check(argv)){ PyErr_SetString(PyExc_TypeError, "posix_spawn: argv must be a tuple or list"); goto fail; @@ -5176,44 +5183,85 @@ os_posixspawn_impl(PyObject *module, path_t *path, PyObject *argv, file_actionsp = &_file_actions; - PyObject* open_action = PyObject_GetAttrString(file_actions, "_open_action"); - if (open_action != Py_None){ - long open_fd = PyLong_AsLong(PyTuple_GetItem(open_action, 0)); - char* open_path = PyBytes_AsString(PyTuple_GetItem(open_action, 1)); - long open_oflag = PyLong_AsLong(PyTuple_GetItem(open_action, 2)); - long open_mode = PyLong_AsLong(PyTuple_GetItem(open_action, 3)); - posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode); - } - PyObject* close_action = PyObject_GetAttrString(file_actions, "_close_action"); - if (close_action != Py_None){ - long close_fd = PyLong_AsLong(PyTuple_GetItem(close_action, 0)); - posix_spawn_file_actions_addclose(file_actionsp, close_fd); + PyObject* seq = PySequence_Fast(file_actions, "file_actions must be a sequence"); + if(seq == NULL){ + goto fail; } + PyObject* file_actions_obj; + PyObject* mode_obj; - PyObject* dup2_action = PyObject_GetAttrString(file_actions, "_dup2_action"); - if (dup2_action != Py_None){ - long fd1 = PyLong_AsLong(PyTuple_GetItem(dup2_action, 0)); - long fd2 = PyLong_AsLong(PyTuple_GetItem(dup2_action, 1)); - posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2); - } + int mode; + for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { + file_actions_obj = PySequence_Fast_GET_ITEM(seq, i); - } + if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)){ + PyErr_SetString(PyExc_TypeError,"Each file_action element must be a non empty sequence"); + goto fail; + } + mode_obj = PySequence_Fast_GET_ITEM(file_actions_obj, 0); + int mode = PyLong_AsLong(mode_obj); - _Py_BEGIN_SUPPRESS_IPH - posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); - return PyLong_FromPid(pid); - _Py_END_SUPPRESS_IPH + /* Populate the file_actions object */ - path_error(path); + switch(mode) { - free_string_array(envlist, envc); - fail: - if (argvlist) - free_string_array(argvlist, argc); - return NULL; + case POSIX_SPAWN_OPEN: + if(PySequence_Size(file_actions_obj) != 5){ + PyErr_SetString(PyExc_TypeError,"A open file_action object must have 5 elements"); + goto fail; + } + + long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); + char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2)); + long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3)); + long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4)); + posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode); + break; + + case POSIX_SPAWN_CLOSE: + if(PySequence_Size(file_actions_obj) != 2){ + PyErr_SetString(PyExc_TypeError,"A close file_action object must have 2 elements"); + goto fail; + } + + long close_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); + posix_spawn_file_actions_addclose(file_actionsp, close_fd); + break; + + case POSIX_SPAWN_DUP2: + if(PySequence_Size(file_actions_obj) != 3){ + PyErr_SetString(PyExc_TypeError,"A dup2 file_action object must have 3 elements"); + goto fail; + } + + long fd1 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); + long fd2 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 2)); + posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2); + break; + + default: + PyErr_SetString(PyExc_TypeError,"Unknown file_actions identifier"); + goto fail; + } + } + Py_DECREF(seq); +} + +_Py_BEGIN_SUPPRESS_IPH + posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); + return PyLong_FromPid(pid); +_Py_END_SUPPRESS_IPH + +path_error(path); + +free_string_array(envlist, envc); +fail: +if (argvlist) + free_string_array(argvlist, argc); +return NULL; } @@ -12731,7 +12779,7 @@ static PyMethodDef posix_methods[] = { OS_NICE_METHODDEF OS_GETPRIORITY_METHODDEF OS_SETPRIORITY_METHODDEF - OS_POSIXSPAWN_METHODDEF + OS_POSIX_SPAWN_METHODDEF #ifdef HAVE_READLINK {"readlink", (PyCFunction)posix_readlink, METH_VARARGS | METH_KEYWORDS, @@ -13286,6 +13334,13 @@ all_ins(PyObject *m) if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; #endif +/* constants for posix_spawn */ +#ifdef HAVE_POSIX_SPAWN + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; + if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; +#endif + #ifdef HAVE_SPAWNV if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; From 90ed19918af25a7f3d067811664de4c06624e604 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 10 Jan 2018 22:45:56 +0000 Subject: [PATCH 5/8] Clean implementation of posix_spawn --- Modules/posixmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index dda27f44d6e130..1e3a2e8bd9b572 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5191,7 +5191,6 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, PyObject* file_actions_obj; PyObject* mode_obj; - int mode; for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { file_actions_obj = PySequence_Fast_GET_ITEM(seq, i); @@ -5215,7 +5214,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, } long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2)); + const char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2)); long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3)); long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4)); posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode); From 6ba804da7b7bb057a9e866b1cbd62d11521e17ac Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 18 Jan 2018 23:32:50 +0000 Subject: [PATCH 6/8] Fix function name in tests and update NEWS --- Lib/test/test_posix.py | 4 ++-- .../2018-01-06-01-14-53.bpo-20104.9DkKb8.rst | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 93b154947bff1c..8ada0e3ab3c7d6 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -177,13 +177,13 @@ def test_fexecve(self): os.close(fp) - @unittest.skipUnless(hasattr(os, 'posixspawn'), "test needs os.posix_spawn") + @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") def test_posix_spawn(self): pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ,[]) self.assertEqual(os.waitpid(pid,0),(pid,0)) - @unittest.skipUnless(hasattr(os, 'posixspawn'), "test needs os.posix_spawn") + @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") def test_posix_spawn_file_actions(self): file_actions = [] file_actions.append((0,3,os.path.realpath(__file__),0,0)) diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst b/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst index bc9a089902de1f..cb69f320dfb806 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2018-01-06-01-14-53.bpo-20104.9DkKb8.rst @@ -1,2 +1 @@ -Expose posix_spawn and a FileActions object to work with said function in -the os module. +Expose posix_spawn as a low level API in the os module. From 88831ec8feaeb472498948a105b0c07f48dda076 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 19 Jan 2018 22:52:07 +0000 Subject: [PATCH 7/8] Fixed configure script --- @test_11613_tmp | 0 @test_1931_tmp | 0 @test_20400_tmp | 0 @test_22339_tmp | 0 @test_24611_tmp | 0 @test_24744_tmp | 0 @test_24872_tmp | 0 @test_25176_tmp | 0 @test_25627_tmp | 0 @test_25914_tmp | 0 @test_26145_tmp | 0 @test_26441_tmp | 0 @test_26725_tmp | 0 @test_26954_tmp | 0 @test_27185_tmp | 0 @test_27415_tmp | 0 @test_27645_tmp | 0 @test_28387_tmp | 0 @test_29448_tmp | 0 @test_29799_tmp | 0 @test_30178_tmp | 0 @test_30414_tmp | 0 @test_30664_tmp | 0 @test_30905_tmp | 0 @test_31032_tmp | 0 @test_31180_tmp | 0 @test_31348_tmp | 0 @test_31581_tmp | 0 @test_31814_tmp | 0 @test_32141_tmp | 0 @test_32372_tmp | 0 @test_32651_tmp | 0 @test_3753_tmp | 0 @test_9809_tmp | 0 configure | 5 +++++ configure.ac | 5 +++++ pyconfig.h.in | 18 ++++++++++++++++++ 37 files changed, 28 insertions(+) delete mode 100644 @test_11613_tmp delete mode 100644 @test_1931_tmp delete mode 100644 @test_20400_tmp delete mode 100644 @test_22339_tmp delete mode 100644 @test_24611_tmp delete mode 100644 @test_24744_tmp delete mode 100644 @test_24872_tmp delete mode 100644 @test_25176_tmp delete mode 100644 @test_25627_tmp delete mode 100644 @test_25914_tmp delete mode 100644 @test_26145_tmp delete mode 100644 @test_26441_tmp delete mode 100644 @test_26725_tmp delete mode 100644 @test_26954_tmp delete mode 100644 @test_27185_tmp delete mode 100644 @test_27415_tmp delete mode 100644 @test_27645_tmp delete mode 100644 @test_28387_tmp delete mode 100644 @test_29448_tmp delete mode 100644 @test_29799_tmp delete mode 100644 @test_30178_tmp delete mode 100644 @test_30414_tmp delete mode 100644 @test_30664_tmp delete mode 100644 @test_30905_tmp delete mode 100644 @test_31032_tmp delete mode 100644 @test_31180_tmp delete mode 100644 @test_31348_tmp delete mode 100644 @test_31581_tmp delete mode 100644 @test_31814_tmp delete mode 100644 @test_32141_tmp delete mode 100644 @test_32372_tmp delete mode 100644 @test_32651_tmp delete mode 100644 @test_3753_tmp delete mode 100644 @test_9809_tmp diff --git a/@test_11613_tmp b/@test_11613_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_1931_tmp b/@test_1931_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_20400_tmp b/@test_20400_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_22339_tmp b/@test_22339_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_24611_tmp b/@test_24611_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_24744_tmp b/@test_24744_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_24872_tmp b/@test_24872_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_25176_tmp b/@test_25176_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_25627_tmp b/@test_25627_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_25914_tmp b/@test_25914_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_26145_tmp b/@test_26145_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_26441_tmp b/@test_26441_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_26725_tmp b/@test_26725_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_26954_tmp b/@test_26954_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_27185_tmp b/@test_27185_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_27415_tmp b/@test_27415_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_27645_tmp b/@test_27645_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_28387_tmp b/@test_28387_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_29448_tmp b/@test_29448_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_29799_tmp b/@test_29799_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_30178_tmp b/@test_30178_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_30414_tmp b/@test_30414_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_30664_tmp b/@test_30664_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_30905_tmp b/@test_30905_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_31032_tmp b/@test_31032_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_31180_tmp b/@test_31180_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_31348_tmp b/@test_31348_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_31581_tmp b/@test_31581_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_31814_tmp b/@test_31814_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_32141_tmp b/@test_32141_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_32372_tmp b/@test_32372_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_32651_tmp b/@test_32651_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_3753_tmp b/@test_3753_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/@test_9809_tmp b/@test_9809_tmp deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/configure b/configure index 6ce0728af1190b..ab5e33e3c6afed 100755 --- a/configure +++ b/configure @@ -11197,8 +11197,13 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mmap \ memrchr mbrtowc mkdirat mkfifo \ mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ +<<<<<<< HEAD posix_fallocate posix_fadvise pread preadv preadv2 \ pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ +======= + posix_fallocate posix_fadvise posix_spawn pread \ + pthread_init pthread_kill putenv pwrite readlink readlinkat readv realpath renameat \ +>>>>>>> Fixed configure script sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ diff --git a/configure.ac b/configure.ac index b901f807657c0c..5af7a6b3ce788f 100644 --- a/configure.ac +++ b/configure.ac @@ -3431,8 +3431,13 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mmap \ memrchr mbrtowc mkdirat mkfifo \ mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ +<<<<<<< HEAD posix_fallocate posix_fadvise pread preadv preadv2 \ pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ +======= + posix_fallocate posix_fadvise posix_spawn pread \ + pthread_init pthread_kill putenv pwrite readlink readlinkat readv realpath renameat \ +>>>>>>> Fixed configure script sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ diff --git a/pyconfig.h.in b/pyconfig.h.in index 27fe136a976427..2f0cd86f800fb7 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -131,6 +131,9 @@ /* Define if the C compiler supports computed gotos. */ #undef HAVE_COMPUTED_GOTOS +/* Define to 1 if you have the `configure' function. */ +#undef HAVE_CONFIGURE + /* Define to 1 if you have the `confstr' function. */ #undef HAVE_CONFSTR @@ -327,6 +330,9 @@ /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE +/* Define to 1 if you have the `Fixed' function. */ +#undef HAVE_FIXED + /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK @@ -491,6 +497,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H +/* Define to 1 if you have the `HEAD' function. */ +#undef HAVE_HEAD + /* Define if you have the 'hstrerror' function. */ #undef HAVE_HSTRERROR @@ -707,6 +716,9 @@ /* Define to 1 if you have the `posix_fallocate' function. */ #undef HAVE_POSIX_FALLOCATE +/* Define to 1 if you have the `posix_spawn' function. */ +#undef HAVE_POSIX_SPAWN + /* Define to 1 if you have the `pread' function. */ #undef HAVE_PREAD @@ -818,6 +830,9 @@ /* Define to 1 if you have the `sched_setscheduler' function. */ #undef HAVE_SCHED_SETSCHEDULER +/* Define to 1 if you have the `script' function. */ +#undef HAVE_SCRIPT + /* Define to 1 if you have the `sem_getvalue' function. */ #undef HAVE_SEM_GETVALUE @@ -1261,6 +1276,9 @@ /* Define to 1 if you have the `_getpty' function. */ #undef HAVE__GETPTY +/* Define to 1 if you have the `=======' function. */ +#undef HAVE________ + /* Define if log1p(-0.) is 0. rather than -0. */ #undef LOG1P_DROPS_ZERO_SIGN From cb440d5d975f413f59709e90d85d6de93721bd74 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Sun, 28 Jan 2018 20:44:44 +0000 Subject: [PATCH 8/8] Add error checking, correct style --- Modules/posixmodule.c | 44 +++++++++++++++++++++++++++++++++---------- configure | 7 +------ configure.ac | 7 +------ pyconfig.h.in | 15 --------------- 4 files changed, 36 insertions(+), 37 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 1e3a2e8bd9b572..4c0392e22c3bec 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5214,9 +5214,21 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, } long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); + if(PyErr_Occurred()) { + goto fail; + } const char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2)); + if(open_path == NULL){ + goto fail; + } long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3)); + if(PyErr_Occurred()) { + goto fail; + } long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4)); + if(PyErr_Occurred()) { + goto fail; + } posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode); break; @@ -5227,6 +5239,9 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, } long close_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); + if(PyErr_Occurred()) { + goto fail; + } posix_spawn_file_actions_addclose(file_actionsp, close_fd); break; @@ -5237,7 +5252,13 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, } long fd1 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); + if(PyErr_Occurred()) { + goto fail; + } long fd2 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 2)); + if(PyErr_Occurred()) { + goto fail; + } posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2); break; @@ -5249,22 +5270,25 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, Py_DECREF(seq); } -_Py_BEGIN_SUPPRESS_IPH - posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); - return PyLong_FromPid(pid); -_Py_END_SUPPRESS_IPH + _Py_BEGIN_SUPPRESS_IPH + posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); + return PyLong_FromPid(pid); + _Py_END_SUPPRESS_IPH -path_error(path); + path_error(path); + + free_string_array(envlist, envc); -free_string_array(envlist, envc); fail: -if (argvlist) - free_string_array(argvlist, argc); -return NULL; + + if (argvlist) { + free_string_array(argvlist, argc); + } + return NULL; } -#endif +#endif /* HAVE_POSIX_SPAWN */ #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) diff --git a/configure b/configure index ab5e33e3c6afed..f94d16bf0b0c5f 100755 --- a/configure +++ b/configure @@ -11197,13 +11197,8 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mmap \ memrchr mbrtowc mkdirat mkfifo \ mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ -<<<<<<< HEAD - posix_fallocate posix_fadvise pread preadv preadv2 \ + posix_fallocate posix_fadvise posix_spawn pread preadv preadv2 \ pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ -======= - posix_fallocate posix_fadvise posix_spawn pread \ - pthread_init pthread_kill putenv pwrite readlink readlinkat readv realpath renameat \ ->>>>>>> Fixed configure script sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ diff --git a/configure.ac b/configure.ac index 5af7a6b3ce788f..65248630b6e1a8 100644 --- a/configure.ac +++ b/configure.ac @@ -3431,13 +3431,8 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mmap \ memrchr mbrtowc mkdirat mkfifo \ mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \ -<<<<<<< HEAD - posix_fallocate posix_fadvise pread preadv preadv2 \ + posix_fallocate posix_fadvise posix_spawn pread preadv preadv2 \ pthread_init pthread_kill putenv pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \ -======= - posix_fallocate posix_fadvise posix_spawn pread \ - pthread_init pthread_kill putenv pwrite readlink readlinkat readv realpath renameat \ ->>>>>>> Fixed configure script sem_open sem_timedwait sem_getvalue sem_unlink sendfile setegid seteuid \ setgid sethostname \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ diff --git a/pyconfig.h.in b/pyconfig.h.in index 2f0cd86f800fb7..a18e3ca854e629 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -131,9 +131,6 @@ /* Define if the C compiler supports computed gotos. */ #undef HAVE_COMPUTED_GOTOS -/* Define to 1 if you have the `configure' function. */ -#undef HAVE_CONFIGURE - /* Define to 1 if you have the `confstr' function. */ #undef HAVE_CONFSTR @@ -330,9 +327,6 @@ /* Define to 1 if you have the `finite' function. */ #undef HAVE_FINITE -/* Define to 1 if you have the `Fixed' function. */ -#undef HAVE_FIXED - /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK @@ -497,9 +491,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H -/* Define to 1 if you have the `HEAD' function. */ -#undef HAVE_HEAD - /* Define if you have the 'hstrerror' function. */ #undef HAVE_HSTRERROR @@ -830,9 +821,6 @@ /* Define to 1 if you have the `sched_setscheduler' function. */ #undef HAVE_SCHED_SETSCHEDULER -/* Define to 1 if you have the `script' function. */ -#undef HAVE_SCRIPT - /* Define to 1 if you have the `sem_getvalue' function. */ #undef HAVE_SEM_GETVALUE @@ -1276,9 +1264,6 @@ /* Define to 1 if you have the `_getpty' function. */ #undef HAVE__GETPTY -/* Define to 1 if you have the `=======' function. */ -#undef HAVE________ - /* Define if log1p(-0.) is 0. rather than -0. */ #undef LOG1P_DROPS_ZERO_SIGN