Issue #25654:
* multiprocessing: open file with closefd=False to avoid ResourceWarning
* _test_multiprocessing: open file with O_EXCL to detect bugs in tests (if a
previous test forgot to remove TESTFN)
* test_sys_exit(): remove TESTFN after each loop iteration
Initial patch written by Serhiy Storchaka.
diff --git a/Lib/multiprocessing/forkserver.py b/Lib/multiprocessing/forkserver.py
index b27cba5..ad01ede 100644
--- a/Lib/multiprocessing/forkserver.py
+++ b/Lib/multiprocessing/forkserver.py
@@ -147,13 +147,7 @@
except ImportError:
pass
- # close sys.stdin
- if sys.stdin is not None:
- try:
- sys.stdin.close()
- sys.stdin = open(os.devnull)
- except (OSError, ValueError):
- pass
+ util._close_stdin()
# ignoring SIGCHLD means no need to reap zombie processes
handler = signal.signal(signal.SIGCHLD, signal.SIG_IGN)
diff --git a/Lib/multiprocessing/process.py b/Lib/multiprocessing/process.py
index 68959bf..bca8b7a 100644
--- a/Lib/multiprocessing/process.py
+++ b/Lib/multiprocessing/process.py
@@ -234,12 +234,7 @@
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
+ util._close_stdin()
old_process = _current_process
_current_process = self
try:
diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py
index ea5443d..1a2c0db 100644
--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -9,6 +9,7 @@
import os
import itertools
+import sys
import weakref
import atexit
import threading # we want threading to install it's
@@ -356,6 +357,28 @@
assert fds[-1] == MAXFD, 'fd too large'
for i in range(len(fds) - 1):
os.closerange(fds[i]+1, fds[i+1])
+#
+# Close sys.stdin and replace stdin with os.devnull
+#
+
+def _close_stdin():
+ if sys.stdin is None:
+ return
+
+ try:
+ sys.stdin.close()
+ except (OSError, ValueError):
+ pass
+
+ try:
+ fd = os.open(os.devnull, os.O_RDONLY)
+ try:
+ sys.stdin = open(fd, closefd=False)
+ except:
+ os.close(fd)
+ raise
+ except (OSError, ValueError):
+ pass
#
# Start a program with only specified fds kept open