diff options
-rw-r--r-- | Lib/test/test_subprocess.py | 12 | ||||
-rw-r--r-- | Modules/_posixsubprocess.c | 116 |
2 files changed, 5 insertions, 123 deletions
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 7c79365..27ccd3e 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -2147,8 +2147,6 @@ class POSIXProcessTestCase(BaseTestCase): def test_preexec_gc_module_failure(self): # This tests the code that disables garbage collection if the child # process will execute any Python. - def raise_runtime_error(): - raise RuntimeError("this shouldn't escape") enabled = gc.isenabled() orig_gc_disable = gc.disable orig_gc_isenabled = gc.isenabled @@ -2165,16 +2163,6 @@ class POSIXProcessTestCase(BaseTestCase): subprocess.call([sys.executable, '-c', ''], preexec_fn=lambda: None) self.assertTrue(gc.isenabled(), "Popen left gc disabled.") - - gc.disable = raise_runtime_error - self.assertRaises(RuntimeError, subprocess.Popen, - [sys.executable, '-c', ''], - preexec_fn=lambda: None) - - del gc.isenabled # force an AttributeError - self.assertRaises(AttributeError, subprocess.Popen, - [sys.executable, '-c', ''], - preexec_fn=lambda: None) finally: gc.disable = orig_gc_disable gc.isenabled = orig_gc_isenabled diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 3b06516..a58159a 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -69,47 +69,8 @@ #define POSIX_CALL(call) do { if ((call) == -1) goto error; } while (0) -typedef struct { - PyObject* disable; - PyObject* enable; - PyObject* isenabled; -} _posixsubprocessstate; - static struct PyModuleDef _posixsubprocessmodule; -static inline _posixsubprocessstate* -get_posixsubprocess_state(PyObject *module) -{ - void *state = PyModule_GetState(module); - assert(state != NULL); - return (_posixsubprocessstate *)state; -} - -/* If gc was disabled, call gc.enable(). Ignore errors. */ -static void -_enable_gc(int need_to_reenable_gc, PyObject *gc_module, _posixsubprocessstate *state) -{ - PyObject *result; - PyObject *exctype, *val, *tb; - - if (need_to_reenable_gc) { - PyErr_Fetch(&exctype, &val, &tb); - result = PyObject_CallMethodNoArgs( - gc_module, state->enable); - if (result == NULL) { - /* We might have created a child process at this point, we - * we have no good way to handle a failure to reenable GC - * and return information about the child process. */ - PyErr_Print(); - } - Py_XDECREF(result); - if (exctype != NULL) { - PyErr_Restore(exctype, val, tb); - } - } -} - - /* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */ static int _pos_int_from_ascii(const char *name) @@ -780,7 +741,6 @@ subprocess_fork_exec(PyObject *module, PyObject *args) Py_ssize_t arg_num, num_groups = 0; int need_after_fork = 0; int saved_errno = 0; - _posixsubprocessstate *state = get_posixsubprocess_state(module); if (!PyArg_ParseTuple( args, "OOpO!OOiiiiiiiiiiOOOiO:fork_exec", @@ -820,30 +780,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args) /* We need to call gc.disable() when we'll be calling preexec_fn */ if (preexec_fn != Py_None) { - PyObject *result; - - gc_module = PyImport_ImportModule("gc"); - if (gc_module == NULL) - return NULL; - result = PyObject_CallMethodNoArgs( - gc_module, state->isenabled); - if (result == NULL) { - Py_DECREF(gc_module); - return NULL; - } - need_to_reenable_gc = PyObject_IsTrue(result); - Py_DECREF(result); - if (need_to_reenable_gc == -1) { - Py_DECREF(gc_module); - return NULL; - } - result = PyObject_CallMethodNoArgs( - gc_module, state->disable); - if (result == NULL) { - Py_DECREF(gc_module); - return NULL; - } - Py_DECREF(result); + need_to_reenable_gc = PyGC_Disable(); } exec_array = _PySequence_BytesToCharpArray(executable_list); @@ -1068,7 +1005,9 @@ cleanup: if (exec_array) _Py_FreeCharPArray(exec_array); - _enable_gc(need_to_reenable_gc, gc_module, state); + if (need_to_reenable_gc) { + PyGC_Enable(); + } Py_XDECREF(gc_module); return pid == -1 ? NULL : PyLong_FromPid(pid); @@ -1108,67 +1047,22 @@ Raises: Only on an error in the parent process.\n\ PyDoc_STRVAR(module_doc, "A POSIX helper for the subprocess module."); -static int -_posixsubprocess_exec(PyObject *module) -{ - _posixsubprocessstate *state = get_posixsubprocess_state(module); - - state->disable = PyUnicode_InternFromString("disable"); - if (state->disable == NULL) { - return -1; - } - - state->enable = PyUnicode_InternFromString("enable"); - if (state->enable == NULL) { - return -1; - } - - state->isenabled = PyUnicode_InternFromString("isenabled"); - if (state->isenabled == NULL) { - return -1; - } - - return 0; -} - static PyMethodDef module_methods[] = { {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc}, {NULL, NULL} /* sentinel */ }; static PyModuleDef_Slot _posixsubprocess_slots[] = { - {Py_mod_exec, _posixsubprocess_exec}, {0, NULL} }; -static int _posixsubprocess_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(get_posixsubprocess_state(m)->disable); - Py_VISIT(get_posixsubprocess_state(m)->enable); - Py_VISIT(get_posixsubprocess_state(m)->isenabled); - return 0; -} - -static int _posixsubprocess_clear(PyObject *m) { - Py_CLEAR(get_posixsubprocess_state(m)->disable); - Py_CLEAR(get_posixsubprocess_state(m)->enable); - Py_CLEAR(get_posixsubprocess_state(m)->isenabled); - return 0; -} - -static void _posixsubprocess_free(void *m) { - _posixsubprocess_clear((PyObject *)m); -} - static struct PyModuleDef _posixsubprocessmodule = { PyModuleDef_HEAD_INIT, .m_name = "_posixsubprocess", .m_doc = module_doc, - .m_size = sizeof(_posixsubprocessstate), + .m_size = 0, .m_methods = module_methods, .m_slots = _posixsubprocess_slots, - .m_traverse = _posixsubprocess_traverse, - .m_clear = _posixsubprocess_clear, - .m_free = _posixsubprocess_free, }; PyMODINIT_FUNC |