Mercurial > hg
comparison tests/test-stdio.py @ 45147:c2c862b9b544
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.
author | Manuel Jacob <me@manueljacob.de> |
---|---|
date | Fri, 17 Jul 2020 00:37:33 +0200 |
parents | eb26a9cf7821 |
children | a37f290a7124 |
comparison
equal
deleted
inserted
replaced
45146:a0791bfd9cfa | 45147:c2c862b9b544 |
---|---|
12 import sys | 12 import sys |
13 import tempfile | 13 import tempfile |
14 import unittest | 14 import unittest |
15 | 15 |
16 from mercurial import pycompat | 16 from mercurial import pycompat |
17 | |
18 | |
19 if pycompat.ispy3: | |
20 | |
21 def set_noninheritable(fd): | |
22 # On Python 3, file descriptors are non-inheritable by default. | |
23 pass | |
24 | |
25 | |
26 else: | |
27 if pycompat.iswindows: | |
28 # unused | |
29 set_noninheritable = None | |
30 else: | |
31 import fcntl | |
32 | |
33 def set_noninheritable(fd): | |
34 old = fcntl.fcntl(fd, fcntl.F_GETFD) | |
35 fcntl.fcntl(fd, fcntl.F_SETFD, old | fcntl.FD_CLOEXEC) | |
17 | 36 |
18 | 37 |
19 TEST_BUFFERING_CHILD_SCRIPT = r''' | 38 TEST_BUFFERING_CHILD_SCRIPT = r''' |
20 import os | 39 import os |
21 | 40 |
62 os.close(fd) | 81 os.close(fd) |
63 except EnvironmentError: | 82 except EnvironmentError: |
64 pass | 83 pass |
65 | 84 |
66 | 85 |
86 # In the following, we set the FDs non-inheritable mainly to make it possible | |
87 # for tests to close the receiving end of the pipe / PTYs. | |
88 | |
89 | |
67 @contextlib.contextmanager | 90 @contextlib.contextmanager |
68 def _devnull(): | 91 def _devnull(): |
69 devnull = os.open(os.devnull, os.O_WRONLY) | 92 devnull = os.open(os.devnull, os.O_WRONLY) |
93 # We don't have a receiving end, so it's not worth the effort on Python 2 | |
94 # on Windows to make the FD non-inheritable. | |
70 with _closing([devnull]): | 95 with _closing([devnull]): |
71 yield (None, devnull) | 96 yield (None, devnull) |
72 | 97 |
73 | 98 |
74 @contextlib.contextmanager | 99 @contextlib.contextmanager |
75 def _pipes(): | 100 def _pipes(): |
76 rwpair = os.pipe() | 101 rwpair = os.pipe() |
102 # Pipes are already non-inheritable on Windows. | |
103 if not pycompat.iswindows: | |
104 set_noninheritable(rwpair[0]) | |
105 set_noninheritable(rwpair[1]) | |
77 with _closing(rwpair): | 106 with _closing(rwpair): |
78 yield rwpair | 107 yield rwpair |
79 | 108 |
80 | 109 |
81 @contextlib.contextmanager | 110 @contextlib.contextmanager |
84 raise unittest.SkipTest("PTYs are not supported on Windows") | 113 raise unittest.SkipTest("PTYs are not supported on Windows") |
85 import pty | 114 import pty |
86 import tty | 115 import tty |
87 | 116 |
88 rwpair = pty.openpty() | 117 rwpair = pty.openpty() |
118 set_noninheritable(rwpair[0]) | |
119 set_noninheritable(rwpair[1]) | |
89 with _closing(rwpair): | 120 with _closing(rwpair): |
90 tty.setraw(rwpair[0]) | 121 tty.setraw(rwpair[0]) |
91 yield rwpair | 122 yield rwpair |
92 | 123 |
93 | 124 |