Show More
@@ -1,152 +1,152 b'' | |||
|
1 | 1 | #!/usr/bin/env python3 |
|
2 | 2 | from __future__ import print_function |
|
3 | 3 | |
|
4 | 4 | import io |
|
5 | 5 | import os |
|
6 | 6 | import subprocess |
|
7 | 7 | import sys |
|
8 | 8 | import time |
|
9 | 9 | |
|
10 |
# we cannot use mercurial.testing as long as python2 is not dropped as the test |
|
|
10 | # we cannot use mercurial.testing as long as python2 is not dropped as the test | |
|
11 | # will only install the mercurial module for python2 in python2 run | |
|
12 | if sys.version_info[0] < 3: | |
|
13 | print('SIGPIPE-HELPER: script should run with Python 3', file=sys.stderr) | |
|
14 | sys.exit(255) | |
|
11 | 15 | |
|
12 | 16 | if isinstance(sys.stdout.buffer, io.BufferedWriter): |
|
13 | 17 | print('SIGPIPE-HELPER: script need unbuffered output', file=sys.stderr) |
|
14 | 18 | sys.exit(255) |
|
15 | 19 | |
|
16 | 20 | DEBUG_FILE = os.environ.get('SIGPIPE_REMOTE_DEBUG_FILE') |
|
17 | 21 | if DEBUG_FILE is None: |
|
18 | 22 | debug_stream = sys.stderr.buffer |
|
19 | 23 | else: |
|
20 | 24 | debug_stream = open(DEBUG_FILE, 'bw', buffering=0) |
|
21 | 25 | |
|
22 | 26 | SYNCFILE1 = os.environ.get('SYNCFILE1') |
|
23 | 27 | SYNCFILE2 = os.environ.get('SYNCFILE2') |
|
24 | 28 | if SYNCFILE1 is None: |
|
25 | 29 | print('SIGPIPE-HELPER: missing variable $SYNCFILE1', file=sys.stderr) |
|
26 | 30 | sys.exit(255) |
|
27 | 31 | if SYNCFILE2 is None: |
|
28 | 32 | print('SIGPIPE-HELPER: missing variable $SYNCFILE2', file=sys.stderr) |
|
29 | 33 | sys.exit(255) |
|
30 | 34 | |
|
31 | 35 | |
|
32 | 36 | def _timeout_factor(): |
|
33 | 37 | """return the current modification to timeout""" |
|
34 | 38 | default = int(os.environ.get('HGTEST_TIMEOUT_DEFAULT', 360)) |
|
35 | 39 | current = int(os.environ.get('HGTEST_TIMEOUT', default)) |
|
36 | 40 | if current == 0: |
|
37 | 41 | return 1 |
|
38 | 42 | return current / float(default) |
|
39 | 43 | |
|
40 | 44 | |
|
41 | 45 | def wait_file(path, timeout=10): |
|
42 | 46 | timeout *= _timeout_factor() |
|
43 | 47 | start = time.time() |
|
44 | 48 | while not os.path.exists(path): |
|
45 | 49 | if (time.time() - start) > timeout: |
|
46 | 50 | raise RuntimeError(b"timed out waiting for file: %s" % path) |
|
47 | 51 | time.sleep(0.01) |
|
48 | 52 | |
|
49 | 53 | |
|
50 | 54 | def write_file(path, content=b''): |
|
51 | 55 | with open(path, 'wb') as f: |
|
52 | 56 | f.write(content) |
|
53 | 57 | |
|
54 | 58 | |
|
55 | 59 | # end of mercurial.testing content |
|
56 | 60 | |
|
57 | if sys.version_info[0] < 3: | |
|
58 | print('SIGPIPE-HELPER: script should run with Python 3', file=sys.stderr) | |
|
59 | sys.exit(255) | |
|
60 | ||
|
61 | 61 | |
|
62 | 62 | def sysbytes(s): |
|
63 | 63 | return s.encode('utf-8') |
|
64 | 64 | |
|
65 | 65 | |
|
66 | 66 | def sysstr(s): |
|
67 | 67 | return s.decode('latin-1') |
|
68 | 68 | |
|
69 | 69 | |
|
70 | 70 | debug_stream.write(b'SIGPIPE-HELPER: Starting\n') |
|
71 | 71 | |
|
72 | 72 | TESTLIB_DIR = os.path.dirname(sys.argv[0]) |
|
73 | 73 | WAIT_SCRIPT = os.path.join(TESTLIB_DIR, 'wait-on-file') |
|
74 | 74 | |
|
75 | 75 | hooks_cmd = '%s 10 %s %s' |
|
76 | 76 | hooks_cmd %= ( |
|
77 | 77 | WAIT_SCRIPT, |
|
78 | 78 | SYNCFILE2, |
|
79 | 79 | SYNCFILE1, |
|
80 | 80 | ) |
|
81 | 81 | |
|
82 | 82 | try: |
|
83 | 83 | cmd = ['hg'] |
|
84 | 84 | cmd += sys.argv[1:] |
|
85 | 85 | sub = subprocess.Popen( |
|
86 | 86 | cmd, |
|
87 | 87 | bufsize=0, |
|
88 | 88 | close_fds=True, |
|
89 | 89 | stdin=sys.stdin, |
|
90 | 90 | stdout=subprocess.PIPE, |
|
91 | 91 | stderr=subprocess.PIPE, |
|
92 | 92 | ) |
|
93 | 93 | |
|
94 | 94 | basedir = os.path.dirname(sys.argv[0]) |
|
95 | 95 | worker = os.path.join(basedir, 'sigpipe-worker.py') |
|
96 | 96 | |
|
97 | 97 | cmd = [sys.executable, worker] |
|
98 | 98 | |
|
99 | 99 | stdout_worker = subprocess.Popen( |
|
100 | 100 | cmd, |
|
101 | 101 | bufsize=0, |
|
102 | 102 | close_fds=True, |
|
103 | 103 | stdin=sub.stdout, |
|
104 | 104 | stdout=sys.stdout, |
|
105 | 105 | stderr=sys.stderr, |
|
106 | 106 | ) |
|
107 | 107 | |
|
108 | 108 | stderr_worker = subprocess.Popen( |
|
109 | 109 | cmd, |
|
110 | 110 | bufsize=0, |
|
111 | 111 | close_fds=True, |
|
112 | 112 | stdin=sub.stderr, |
|
113 | 113 | stdout=sys.stderr, |
|
114 | 114 | stderr=sys.stderr, |
|
115 | 115 | ) |
|
116 | 116 | debug_stream.write(b'SIGPIPE-HELPER: Redirection in place\n') |
|
117 | 117 | os.close(sub.stdout.fileno()) |
|
118 | 118 | os.close(sub.stderr.fileno()) |
|
119 | 119 | debug_stream.write(b'SIGPIPE-HELPER: pipes closed in main\n') |
|
120 | 120 | |
|
121 | 121 | try: |
|
122 | 122 | wait_file(sysbytes(SYNCFILE1)) |
|
123 | 123 | except RuntimeError as exc: |
|
124 | 124 | msg = sysbytes(str(exc)) |
|
125 | 125 | debug_stream.write(b'SIGPIPE-HELPER: wait failed: %s\n' % msg) |
|
126 | 126 | else: |
|
127 | 127 | debug_stream.write(b'SIGPIPE-HELPER: SYNCFILE1 detected\n') |
|
128 | 128 | stdout_worker.kill() |
|
129 | 129 | stderr_worker.kill() |
|
130 | 130 | stdout_worker.wait(10) |
|
131 | 131 | stderr_worker.wait(10) |
|
132 | 132 | debug_stream.write(b'SIGPIPE-HELPER: worker killed\n') |
|
133 | 133 | |
|
134 | 134 | debug_stream.write(b'SIGPIPE-HELPER: creating SYNCFILE2\n') |
|
135 | 135 | write_file(sysbytes(SYNCFILE2)) |
|
136 | 136 | finally: |
|
137 | 137 | debug_stream.write(b'SIGPIPE-HELPER: Shutting down\n') |
|
138 | 138 | if not sys.stdin.closed: |
|
139 | 139 | sys.stdin.close() |
|
140 | 140 | try: |
|
141 | 141 | sub.wait(timeout=30) |
|
142 | 142 | except subprocess.TimeoutExpired: |
|
143 | 143 | msg = b'SIGPIPE-HELPER: Server process failed to terminate\n' |
|
144 | 144 | debug_stream.write(msg) |
|
145 | 145 | sub.kill() |
|
146 | 146 | sub.wait() |
|
147 | 147 | msg = b'SIGPIPE-HELPER: Server process killed\n' |
|
148 | 148 | else: |
|
149 | 149 | msg = b'SIGPIPE-HELPER: Server process terminated with status %d\n' |
|
150 | 150 | msg %= sub.returncode |
|
151 | 151 | debug_stream.write(msg) |
|
152 | 152 | debug_stream.write(b'SIGPIPE-HELPER: Shut down\n') |
General Comments 0
You need to be logged in to leave comments.
Login now