diff -r d64bb25cf797 Lib/multiprocessing/forkserver.py --- a/Lib/multiprocessing/forkserver.py Wed Nov 18 02:45:51 2015 +0000 +++ b/Lib/multiprocessing/forkserver.py Wed Nov 18 14:15:39 2015 +0200 @@ -154,6 +154,12 @@ def main(listener_fd, alive_r, preload, sys.stdin = open(os.devnull) except (OSError, ValueError): pass + if sys.__stdin__ is not None: + try: + sys.__stdin__.close() + except (OSError, ValueError): + pass + sys.__stdin__ = sys.stdin # ignoring SIGCHLD means no need to reap zombie processes handler = signal.signal(signal.SIGCHLD, signal.SIG_IGN) diff -r d64bb25cf797 Lib/multiprocessing/process.py --- a/Lib/multiprocessing/process.py Wed Nov 18 02:45:51 2015 +0000 +++ b/Lib/multiprocessing/process.py Wed Nov 18 14:15:39 2015 +0200 @@ -234,12 +234,20 @@ class BaseProcess(object): context._force_start_method(self._start_method) _process_counter = itertools.count(1) _children = set() + if sys.stdin is not None: try: sys.stdin.close() sys.stdin = open(os.devnull) except (OSError, ValueError): pass + if sys.__stdin__ is not None: + try: + sys.__stdin__.close() + except (OSError, ValueError): + pass + sys.__stdin__ = sys.stdin + old_process = _current_process _current_process = self try: diff -r d64bb25cf797 Lib/test/_test_multiprocessing.py --- a/Lib/test/_test_multiprocessing.py Wed Nov 18 02:45:51 2015 +0000 +++ b/Lib/test/_test_multiprocessing.py Wed Nov 18 14:15:39 2015 +0200 @@ -455,13 +455,13 @@ class _TestSubclassingProcess(BaseTestCa @classmethod def _test_stderr_flush(cls, testfn): - sys.stderr = open(testfn, 'w') + sys.__stderr__ = sys.stderr = open(testfn, 'w') 1/0 # MARKER @classmethod def _test_sys_exit(cls, reason, testfn): - sys.stderr = open(testfn, 'w') + sys.__stderr__ = sys.stderr = open(testfn, 'w') sys.exit(reason) def test_sys_exit(self): diff -r d64bb25cf797 Python/import.c --- a/Python/import.c Wed Nov 18 02:45:51 2015 +0000 +++ b/Python/import.c Wed Nov 18 14:15:39 2015 +0200 @@ -463,6 +463,30 @@ PyImport_Cleanup(void) Py_DECREF(weaklist); } + for (p = sys_files+2; *p != NULL; p++) { + if (Py_VerboseFlag) + PySys_WriteStderr("# flush sys.%s\n", *p); + value = PyDict_GetItemString(interp->sysdict, *p); + if (value != NULL && value != Py_None) { + PyObject_CallMethod(value, "flush", ""); + PyErr_Clear(); + } + } + for (p = sys_files; *p != NULL; p++) { + if (Py_VerboseFlag) + PySys_WriteStderr("# close sys.%s\n", *p); + value = PyDict_GetItemString(interp->sysdict, *p); + if (value != NULL && value != Py_None) { + PyObject_CallMethod(value, "close", ""); + PyErr_Clear(); + } + } + for (p = sys_files; *p != NULL; p++) { + if (Py_VerboseFlag) + PySys_WriteStderr("# clear sys.%s\n", *p); + PyDict_SetItemString(interp->sysdict, *p, Py_None); + } + /* Next, delete sys and builtins (in that order) */ if (Py_VerboseFlag) PySys_FormatStderr("# cleanup[3] wiping sys\n");