Completed
Push — master ( 81e6f9...f36c2e )
by Ionel Cristian
37s
created

test_connection_handler_exec()   B

Complexity

Conditions 6

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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