test_log_fd()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
dl 0
loc 4
rs 10
1
from __future__ import print_function
2
3
import imp
4
import os
5
import platform
6
import re
7
import select
8
import signal
9
import socket
10
import sys
11
import time
12
from contextlib import closing
13
14
import requests
15
from process_tests import TestProcess
16
from process_tests import TestSocket
17
from process_tests import dump_on_error
18
from process_tests import wait_for_strings
19
from pytest import mark
20
from pytest import raises
21
22
TIMEOUT = int(os.getenv('MANHOLE_TEST_TIMEOUT', 10))
23
SOCKET_PATH = '/tmp/manhole-socket'
24
HELPER = os.path.join(os.path.dirname(__file__), 'helper.py')
25
26
27
def is_module_available(mod):
28
    try:
29
        return imp.find_module(mod)
30
    except ImportError:
31
        return False
32
33
34
def connect_to_manhole(uds_path):
35
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
36
    sock.settimeout(0.5)
37
    for i in range(TIMEOUT):
38
        try:
39
            sock.connect(uds_path)
40
            return sock
41
        except Exception as exc:
42
            print('Failed to connect to %s: %s' % (uds_path, exc))
43
            if i + 1 == TIMEOUT:
44
                sock.close()
45
                raise
46
            time.sleep(1)
47
48
49
def assert_manhole_running(proc, uds_path, oneshot=False, extra=None):
50
    sock = connect_to_manhole(uds_path)
51
    with TestSocket(sock) as client:
52
        with dump_on_error(client.read):
53
            wait_for_strings(client.read, TIMEOUT, "ProcessID", "ThreadID", ">>>")
54
            sock.send(b"print('FOOBAR')\n")
55
            wait_for_strings(client.read, TIMEOUT, "FOOBAR")
56
            wait_for_strings(proc.read, TIMEOUT, 'UID:%s' % os.getuid())
57
            if extra:
58
                extra(client)
59
    wait_for_strings(proc.read, TIMEOUT, 'Cleaned up.', *[] if oneshot else ['Waiting for new connection'])
60
61
62
def test_log_when_uninstalled():
63
    import manhole
64
65
    raises(manhole.NotInstalled, manhole._LOG, "whatever")
66
67
68
def test_log_fd(capfd):
69
    with TestProcess(sys.executable, HELPER, 'test_log_fd') as proc:
70
        with dump_on_error(proc.read):
71
            wait_for_strings(proc.read, TIMEOUT, "]: whatever-1", "]: whatever-2")
72
73
74
def test_log_fh(monkeypatch, capfd):
75
    with TestProcess(sys.executable, HELPER, 'test_log_fh') as proc:
76
        with dump_on_error(proc.read):
77
            wait_for_strings(proc.read, TIMEOUT, 'SUCCESS')
78
79
80
def test_simple():
81
    with TestProcess(sys.executable, HELPER, 'test_simple') as proc:
82
        with dump_on_error(proc.read):
83
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
84
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
85
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
86
            for _ in range(20):
87
                proc.reset()
88
                assert_manhole_running(proc, uds_path)
89
90
91
@mark.parametrize('variant', ['str', 'func'])
92
def test_connection_handler_exec(variant):
93
    with TestProcess(sys.executable, HELPER, 'test_connection_handler_exec_' + variant) as proc:
94
        with dump_on_error(proc.read):
95
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
96
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
97
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
98
            for _ in range(200):
99
                proc.reset()
100
                sock = connect_to_manhole(uds_path)
101
                wait_for_strings(proc.read, TIMEOUT, 'UID:%s' % os.getuid(), )
102
                with TestSocket(sock) as client:
103
                    with dump_on_error(client.read):
104
                        sock.send(b"print('FOOBAR')\n")
105
                        wait_for_strings(proc.read, TIMEOUT, 'FOOBAR')
106
                        sock.send(b"tete()\n")
107
                        wait_for_strings(proc.read, TIMEOUT, 'TETE')
108 View Code Duplication
                        sock.send(b"exit()\n")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
109
                        wait_for_strings(proc.read, TIMEOUT, 'Exiting exec loop.')
110
111
112
def test_install_once():
113
    with TestProcess(sys.executable, HELPER, 'test_install_once') as proc:
114
        with dump_on_error(proc.read):
115
            wait_for_strings(proc.read, TIMEOUT, 'ALREADY_INSTALLED')
116
117
118
def test_install_twice_not_strict():
119
    with TestProcess(sys.executable, HELPER, 'test_install_twice_not_strict') as proc:
120
        with dump_on_error(proc.read):
121
            wait_for_strings(proc.read, TIMEOUT,
122
                             'Not patching os.fork and os.forkpty. Oneshot activation is done by signal')
123
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
124
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
125
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
126
            assert_manhole_running(proc, uds_path)
127
128 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
129
@mark.skipif(is_module_available('eventlet'), reason="evenlet can't deal with extra threads at process exit")
130
def test_daemon_connection():
131
    with TestProcess(sys.executable, HELPER, 'test_daemon_connection') as proc:
132
        with dump_on_error(proc.read):
133
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
134
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
135
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
136
137
            def terminate_and_read(client):
138
                proc.proc.send_signal(signal.SIGINT)
139
                wait_for_strings(proc.read, TIMEOUT, 'Died with KeyboardInterrupt', 'DIED.')
140
                for _ in range(5):
141
                    client.sock.send(b'bogus()\n')
142
                    time.sleep(0.05)
143
                    print(repr(client.sock.recv(1024)))
144
145
            raises((socket.error, OSError), assert_manhole_running, proc, uds_path, extra=terminate_and_read)
146
            wait_for_strings(proc.read, TIMEOUT, 'In atexit handler')
147
148
149
@mark.skipif(is_module_available('eventlet'), reason="evenlet can't deal with extra threads at process exit")
150
def test_non_daemon_connection():
151
    with TestProcess(sys.executable, HELPER, 'test_simple') as proc:
152
        with dump_on_error(proc.read):
153
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
154
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
155
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
156
157
            def terminate_and_read(client):
158
                proc.proc.send_signal(signal.SIGINT)
159
                wait_for_strings(proc.read, TIMEOUT, 'Died with KeyboardInterrupt')
160
                client.sock.send(b'bogus()\n')
161
                wait_for_strings(client.read, TIMEOUT, 'bogus')
162
                client.sock.send(b'doofus()\n')
163
                wait_for_strings(client.read, TIMEOUT, 'doofus')
164
165
            assert_manhole_running(proc, uds_path, extra=terminate_and_read, oneshot=True)
166
            wait_for_strings(proc.read, TIMEOUT, 'In atexit handler')
167
168
169
def test_locals():
170
    with TestProcess(sys.executable, HELPER, 'test_locals') as proc:
171
        with dump_on_error(proc.read):
172
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
173
            check_locals(SOCKET_PATH)
174
175
176
def test_locals_after_fork():
177
    with TestProcess(sys.executable, HELPER, 'test_locals_after_fork') as proc:
178
        with dump_on_error(proc.read):
179
            wait_for_strings(proc.read, TIMEOUT, 'Fork detected')
180
            proc.reset()
181
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
182
            child_uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
183
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
184
            check_locals(child_uds_path)
185
186
187
def check_locals(uds_path):
188
    sock = connect_to_manhole(uds_path)
189
    with TestSocket(sock) as client:
190
        with dump_on_error(client.read):
191
            wait_for_strings(client.read, TIMEOUT, ">>>")
192
            sock.send(b"from __future__ import print_function\n"
193
                      b"print(k1, k2)\n")
194
            wait_for_strings(client.read, TIMEOUT, "v1 v2")
195
196
197
def test_fork_exec():
198
    with TestProcess(sys.executable, HELPER, 'test_fork_exec') as proc:
199
        with dump_on_error(proc.read):
200
            wait_for_strings(proc.read, TIMEOUT, 'SUCCESS')
201
202
203
def test_socket_path():
204
    with TestProcess(sys.executable, HELPER, 'test_socket_path') as proc:
205
        with dump_on_error(proc.read):
206 View Code Duplication
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
207
            proc.reset()
208
            assert_manhole_running(proc, SOCKET_PATH)
209
210
211
def test_socket_path_with_fork():
212
    with TestProcess(sys.executable, '-u', HELPER, 'test_socket_path_with_fork') as proc:
213
        with dump_on_error(proc.read):
214
            wait_for_strings(proc.read, TIMEOUT, 'Not patching os.fork and os.forkpty. Using user socket path')
215
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
216
            sock = connect_to_manhole(SOCKET_PATH)
217
            with TestSocket(sock) as client:
218
                with dump_on_error(client.read):
219
                    wait_for_strings(client.read, TIMEOUT, "ProcessID", "ThreadID", ">>>")
220
                    sock.send(b"print('BEFORE FORK')\n")
221
                    wait_for_strings(client.read, TIMEOUT, "BEFORE FORK")
222
                    time.sleep(2)
223
                    sock.send(b"print('AFTER FORK')\n")
224
                    wait_for_strings(client.read, TIMEOUT, "AFTER FORK")
225
226
227
def test_redirect_stderr_default():
228
    with TestProcess(sys.executable, HELPER, 'test_redirect_stderr_default') as proc:
229
        with dump_on_error(proc.read):
230
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
231
            sock = connect_to_manhole(SOCKET_PATH)
232
            with TestSocket(sock) as client:
233
                with dump_on_error(client.read):
234 View Code Duplication
                    wait_for_strings(client.read, 1, ">>>")
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
235
                    client.reset()
236
                    sock.send(b"import sys\n"
237
                              b"sys.stderr.write('OK')\n")
238
                    wait_for_strings(client.read, 1, "OK")
239
240
241
def test_redirect_stderr_default_dump_stacktraces():
242
    with TestProcess(sys.executable, HELPER, 'test_redirect_stderr_default') as proc:
243
        with dump_on_error(proc.read):
244
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
245
            check_dump_stacktraces(SOCKET_PATH)
246
247
248
def test_redirect_stderr_default_print_tracebacks():
249
    with TestProcess(sys.executable, HELPER, 'test_redirect_stderr_default') as proc:
250
        with dump_on_error(proc.read):
251
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
252
            check_print_tracebacks(SOCKET_PATH)
253
254
255
def test_redirect_stderr_disabled():
256
    with TestProcess(sys.executable, HELPER, 'test_redirect_stderr_disabled') as proc:
257
        with dump_on_error(proc.read):
258
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
259
            sock = connect_to_manhole(SOCKET_PATH)
260
            with TestSocket(sock) as client:
261
                with dump_on_error(client.read):
262
                    wait_for_strings(client.read, 1, ">>>")
263
                    client.reset()
264
                    sock.send(b"import sys\n"
265
                              b"sys.stderr.write('STDERR')\n"
266
                              b"sys.stdout.write('STDOUT')\n")
267
                    wait_for_strings(client.read, 1, "STDOUT")
268
                    assert 'STDERR' not in client.read()
269
270
271
def test_redirect_stderr_disabled_dump_stacktraces():
272
    with TestProcess(sys.executable, HELPER, 'test_redirect_stderr_disabled') as proc:
273
        with dump_on_error(proc.read):
274
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
275
            check_dump_stacktraces(SOCKET_PATH)
276
277
278
def test_redirect_stderr_disabled_print_tracebacks():
279
    with TestProcess(sys.executable, HELPER, 'test_redirect_stderr_disabled') as proc:
280
        with dump_on_error(proc.read):
281
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
282
            check_print_tracebacks(SOCKET_PATH)
283
284
285
def check_dump_stacktraces(uds_path):
286
    sock = connect_to_manhole(uds_path)
287
    with TestSocket(sock) as client:
288
        with dump_on_error(client.read):
289
            wait_for_strings(client.read, 1, ">>>")
290
            sock.send(b"dump_stacktraces()\n")
291
            # Start of dump
292
            wait_for_strings(client.read, 1, "#########", "ThreadID=", "#########")
293
            # End of dump
294
            wait_for_strings(client.read, 1, "#############################################", ">>>")
295
296
297
def check_print_tracebacks(uds_path):
298
    sock = connect_to_manhole(uds_path)
299
    with TestSocket(sock) as client:
300
        with dump_on_error(client.read):
301
            wait_for_strings(client.read, 1, ">>>")
302
            sock.send(b"NO_SUCH_NAME\n")
303
            wait_for_strings(client.read, 1, "NameError:", "name 'NO_SUCH_NAME' is not defined", ">>>")
304
305
306
def test_exit_with_grace():
307
    with TestProcess(sys.executable, '-u', HELPER, 'test_simple') as proc:
308
        with dump_on_error(proc.read):
309
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
310
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
311
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
312
313
            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
314
            sock.settimeout(0.05)
315
            sock.connect(uds_path)
316 View Code Duplication
            with TestSocket(sock) as client:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
317
                with dump_on_error(client.read):
318
                    wait_for_strings(client.read, TIMEOUT, "ThreadID", "ProcessID", ">>>")
319
                    sock.send(b"print('FOOBAR')\n")
320
                    wait_for_strings(client.read, TIMEOUT, "FOOBAR")
321
322
                    wait_for_strings(proc.read, TIMEOUT, 'UID:%s' % os.getuid())
323
                    sock.shutdown(socket.SHUT_WR)
324
                    select.select([sock], [], [], 5)
325
                    sock.recv(1024)
326
                    try:
327
                        sock.shutdown(socket.SHUT_RD)
328
                    except Exception as exc:
329
                        print("Failed to SHUT_RD: %s" % exc)
330
                    try:
331
                        sock.close()
332
                    except Exception as exc:
333
                        print("Failed to close socket: %s" % exc)
334
            wait_for_strings(proc.read, TIMEOUT, 'DONE.', 'Cleaned up.', 'Waiting for new connection')
335
336
337
def test_with_fork():
338 View Code Duplication
    with TestProcess(sys.executable, '-u', HELPER, 'test_with_fork') as proc:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
339
        with dump_on_error(proc.read):
340
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
341
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
342
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
343
            for _ in range(2):
344
                proc.reset()
345
                assert_manhole_running(proc, uds_path)
346
347
            proc.reset()
348
            wait_for_strings(proc.read, TIMEOUT, 'Fork detected')
349
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
350
            new_uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
351
            assert uds_path != new_uds_path
352
353
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
354
            for _ in range(2):
355
                proc.reset()
356
                assert_manhole_running(proc, new_uds_path)
357
358
359
@mark.skipif(hasattr(sys, 'pypy_version_info'), reason="pypy doesn't support forkpty")
360
def test_with_forkpty():
361
    with TestProcess(sys.executable, '-u', HELPER, 'test_with_forkpty') as proc:
362
        with dump_on_error(proc.read):
363
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
364
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
365
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
366
            for _ in range(2):
367
                proc.reset()
368
                assert_manhole_running(proc, uds_path)
369
370
            proc.reset()
371
            wait_for_strings(proc.read, TIMEOUT, 'Fork detected')
372
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
373
            new_uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
374
            assert uds_path != new_uds_path
375
376
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
377
            for _ in range(2):
378
                proc.reset()
379
                assert_manhole_running(proc, new_uds_path)
380
381
382
def test_auth_fail():
383
    with TestProcess(sys.executable, '-u', HELPER, 'test_auth_fail') as proc:
384
        with dump_on_error(proc.read):
385
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
386
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
387
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
388
            with closing(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)) as sock:
389
                sock.settimeout(1)
390
                sock.connect(uds_path)
391
                try:
392
                    assert b"" == sock.recv(1024)
393
                except socket.timeout:
394
                    pass
395
                wait_for_strings(
396
                    proc.read, TIMEOUT,
397
                    "SuspiciousClient: Can't accept client with PID:-1 UID:-1 GID:-1. It doesn't match the current "
398
                    "EUID:",
399
                    'Waiting for new connection'
400
                )
401
                proc.proc.send_signal(signal.SIGINT)
402
403
404
@mark.skipif(not is_module_available('signalfd'), reason="signalfd not available")
405
def test_sigprocmask():
406
    with TestProcess(sys.executable, '-u', HELPER, 'test_signalfd_weirdness') as proc:
407
        with dump_on_error(proc.read):
408
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
409
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
410
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
411
            wait_for_strings(proc.read, TIMEOUT, 'signalled=False')
412
            assert_manhole_running(proc, uds_path)
413
414
415
@mark.skipif(not is_module_available('signalfd'),
416
             reason="signalfd doesn't play well with gevent/eventlet")
417
def test_sigprocmask_negative():
418
    with TestProcess(sys.executable, '-u', HELPER, 'test_signalfd_weirdness_negative') as proc:
419
        with dump_on_error(proc.read):
420
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
421
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
422
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
423
            wait_for_strings(proc.read, TIMEOUT, 'signalled=True')
424
            assert_manhole_running(proc, uds_path)
425
426 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
427
def test_activate_on_usr2():
428
    with TestProcess(sys.executable, '-u', HELPER, 'test_activate_on_usr2') as proc:
429
        with dump_on_error(proc.read):
430
            wait_for_strings(proc.read, TIMEOUT, 'Not patching os.fork and os.forkpty. Activation is done by signal')
431
            raises(AssertionError, wait_for_strings, proc.read, TIMEOUT, '/tmp/manhole-')
432
            proc.signal(signal.SIGUSR2)
433
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
434
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
435
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
436
            assert_manhole_running(proc, uds_path)
437
438
439
def test_activate_on_with_oneshot_on():
440
    with TestProcess(sys.executable, '-u', HELPER, 'test_activate_on_with_oneshot_on') as proc:
441
        with dump_on_error(proc.read):
442
            wait_for_strings(proc.read, TIMEOUT,
443
                             "You cannot do activation of the Manhole thread on the same signal that you want to do "
444
                             "oneshot activation !")
445
446
447
def test_oneshot_on_usr2():
448
    with TestProcess(sys.executable, '-u', HELPER, 'test_oneshot_on_usr2') as proc:
449
        with dump_on_error(proc.read):
450
            wait_for_strings(proc.read, TIMEOUT,
451
                             'Not patching os.fork and os.forkpty. Oneshot activation is done by signal')
452
            raises(AssertionError, wait_for_strings, proc.read, TIMEOUT, '/tmp/manhole-')
453
            proc.signal(signal.SIGUSR2)
454
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
455
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
456
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
457
            assert_manhole_running(proc, uds_path, oneshot=True)
458
459
460
def test_oneshot_on_usr2_error():
461
    with TestProcess(sys.executable, '-u', HELPER, 'test_oneshot_on_usr2') as proc:
462
        with dump_on_error(proc.read):
463
            wait_for_strings(proc.read, TIMEOUT,
464
                             'Not patching os.fork and os.forkpty. Oneshot activation is done by signal')
465
            raises(AssertionError, wait_for_strings, proc.read, TIMEOUT, '/tmp/manhole-')
466
            proc.signal(signal.SIGUSR2)
467
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
468
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
469
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
470 View Code Duplication
            assert_manhole_running(proc, uds_path, oneshot=True,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
471
                                   extra=lambda client: client.sock.send(b"raise SystemExit()\n"))
472
473
            proc.reset()
474
            proc.signal(signal.SIGUSR2)
475
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
476
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
477
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
478
            assert_manhole_running(proc, uds_path, oneshot=True)
479
480
481
def test_interrupt_on_accept():
482
    with TestProcess(sys.executable, '-u', HELPER, 'test_interrupt_on_accept') as proc:
483
        with dump_on_error(proc.read):
484 View Code Duplication
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
485
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
486
            only_on_old_python = ['Waiting for new connection'] if sys.version_info < (3, 5) else []
487
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection', 'Sending signal to manhole thread',
488
                             *only_on_old_python)
489
            assert_manhole_running(proc, uds_path)
490
491
492
def test_environ_variable_activation():
493
    with TestProcess(sys.executable, '-u', HELPER, 'test_environ_variable_activation',
494
                     env=dict(os.environ, PYTHONMANHOLE="oneshot_on='USR2'")) as proc:
495
        with dump_on_error(proc.read):
496
            wait_for_strings(proc.read, TIMEOUT,
497
                             'Not patching os.fork and os.forkpty. Oneshot activation is done by signal')
498
            proc.signal(signal.SIGUSR2)
499
            wait_for_strings(proc.read, TIMEOUT, '/tmp/manhole-')
500
            uds_path = re.findall(r"(/tmp/manhole-\d+)", proc.read())[0]
501
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
502
            assert_manhole_running(proc, uds_path, oneshot=True)
503
504
505
@mark.skipif(not is_module_available('signalfd'), reason="signalfd not available")
506
def test_sigmask():
507
    with TestProcess(sys.executable, HELPER, 'test_sigmask') as proc:
508
        with dump_on_error(proc.read):
509
            wait_for_strings(proc.read, TIMEOUT, 'Waiting for new connection')
510
            sock = connect_to_manhole(SOCKET_PATH)
511
            with TestSocket(sock) as client:
512
                with dump_on_error(client.read):
513
                    wait_for_strings(client.read, 1, ">>>")
514
                    client.reset()
515
                    # Python 2.7 returns [10L], Python 3 returns [10]
516
                    sock.send(b"from __future__ import print_function\n"
517
                              b"import signalfd\n"
518
                              b"mask = signalfd.sigprocmask(signalfd.SIG_BLOCK, [])\n"
519
                              b"print([int(n) for n in mask])\n")
520
                    wait_for_strings(client.read, 1, '%s' % [int(signal.SIGUSR1)])
521
522
523
def test_stderr_doesnt_deadlock():
524
    for _ in range(100):
525
        with TestProcess(sys.executable, HELPER, 'test_stderr_doesnt_deadlock') as proc:
526
            with dump_on_error(proc.read):
527
                wait_for_strings(proc.read, TIMEOUT, 'SUCCESS')
528
529
530
@mark.skipif("platform.python_implementation() == 'PyPy'")
531
def test_uwsgi():
532
    with TestProcess(
533
            'uwsgi',
534
            '--master',
535
            '--processes', '1',
536
            '--no-orphans',
537
            '--log-5xx',
538
            '--single-interpreter',
539
            '--shared-socket', ':0',
540
            '--no-default-app',
541
            '--manage-script-name',
542
            '--http', '=0',
543
            '--mount', '=wsgi:application'
544
    ) as proc:
545
        with dump_on_error(proc.read):
546
            wait_for_strings(proc.read, TIMEOUT, 'uWSGI http bound')
547
            port = re.findall(r"uWSGI http bound on :(\d+) fd", proc.read())[0]
548
            assert requests.get('http://127.0.0.1:%s/' % port).text == 'OK'
549
550
            wait_for_strings(proc.read, TIMEOUT, 'spawned uWSGI worker 1')
551
            pid = re.findall(r"spawned uWSGI worker 1 \(pid: (\d+), ", proc.read())[0]
552
553
            for _ in range(2):
554
                with open('/tmp/manhole-pid', 'w') as fh:
555
                    fh.write(pid)
556
                assert_manhole_running(proc, '/tmp/manhole-%s' % pid, oneshot=True)
557