tests: make pipes / PTYs non-inheritable in test-stdio.py
authorManuel Jacob <me@manueljacob.de>
Fri, 17 Jul 2020 00:37:33 +0200
changeset 45147 c2c862b9b544
parent 45146 a0791bfd9cfa
child 45148 a37f290a7124
tests: make pipes / PTYs non-inheritable in test-stdio.py A following patch requires that to test closing the receiving end of the pipe / PTYs. Even for existing tests, it might be safer to make the lifetime of the pipes / PTYs as short as possible.
tests/test-stdio.py
--- a/tests/test-stdio.py	Thu Jul 16 23:49:04 2020 +0200
+++ b/tests/test-stdio.py	Fri Jul 17 00:37:33 2020 +0200
@@ -16,6 +16,25 @@
 from mercurial import pycompat
 
 
+if pycompat.ispy3:
+
+    def set_noninheritable(fd):
+        # On Python 3, file descriptors are non-inheritable by default.
+        pass
+
+
+else:
+    if pycompat.iswindows:
+        # unused
+        set_noninheritable = None
+    else:
+        import fcntl
+
+        def set_noninheritable(fd):
+            old = fcntl.fcntl(fd, fcntl.F_GETFD)
+            fcntl.fcntl(fd, fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
+
+
 TEST_BUFFERING_CHILD_SCRIPT = r'''
 import os
 
@@ -64,9 +83,15 @@
                 pass
 
 
+# In the following, we set the FDs non-inheritable mainly to make it possible
+# for tests to close the receiving end of the pipe / PTYs.
+
+
 @contextlib.contextmanager
 def _devnull():
     devnull = os.open(os.devnull, os.O_WRONLY)
+    # We don't have a receiving end, so it's not worth the effort on Python 2
+    # on Windows to make the FD non-inheritable.
     with _closing([devnull]):
         yield (None, devnull)
 
@@ -74,6 +99,10 @@
 @contextlib.contextmanager
 def _pipes():
     rwpair = os.pipe()
+    # Pipes are already non-inheritable on Windows.
+    if not pycompat.iswindows:
+        set_noninheritable(rwpair[0])
+        set_noninheritable(rwpair[1])
     with _closing(rwpair):
         yield rwpair
 
@@ -86,6 +115,8 @@
     import tty
 
     rwpair = pty.openpty()
+    set_noninheritable(rwpair[0])
+    set_noninheritable(rwpair[1])
     with _closing(rwpair):
         tty.setraw(rwpair[0])
         yield rwpair