0001-kill-phantomjs-if-stalled-14606.patch
mandayejs/mandaye/utils.py | ||
---|---|---|
17 | 17 |
import json |
18 | 18 |
import subprocess |
19 | 19 |
import logging |
20 |
import multiprocessing |
|
20 | 21 | |
21 | 22 |
from django.conf import settings |
22 | 23 | |
... | ... | |
28 | 29 | |
29 | 30 | |
30 | 31 |
def exec_phantom(data, script='do_login.js'): |
31 |
phantom = subprocess.Popen([ |
|
32 |
settings.PHANTOM_JS_BINARY, |
|
33 |
'--ignore-ssl-errors=yes', '--ssl-protocol=any', |
|
34 |
os.path.join(settings.BASE_DIR, 'mandayejs', script)], |
|
35 |
close_fds=True, |
|
36 |
stdin=subprocess.PIPE, |
|
37 |
stdout=subprocess.PIPE |
|
38 |
) |
|
32 |
result = None |
|
33 |
waiting_time = getattr(settings, 'PHANTOMJS_WAITING_TIME', 10) |
|
34 | ||
35 |
def run(send_end): |
|
36 |
phantom = subprocess.Popen([ |
|
37 |
settings.PHANTOM_JS_BINARY, |
|
38 |
'--ignore-ssl-errors=yes', '--ssl-protocol=any', |
|
39 |
os.path.join(settings.BASE_DIR, 'mandayejs', script)], |
|
40 |
close_fds=True, |
|
41 |
stdin=subprocess.PIPE, |
|
42 |
stdout=subprocess.PIPE |
|
43 |
) |
|
44 |
stdout, stderr = phantom.communicate(json.dumps(data)) |
|
45 | ||
46 |
try: |
|
47 |
result = json.loads(stdout) |
|
48 |
except (ValueError,): |
|
49 |
result = {"result": "failure, couldn't decode JSON"} |
|
50 |
logger.error(stdout) |
|
51 | ||
52 |
if result.get('stderr'): |
|
53 |
logger.warning(result['stderr']) |
|
54 | ||
55 |
send_end.send(result) |
|
56 | ||
57 |
recv_end, send_end = multiprocessing.Pipe(False) |
|
58 |
process = multiprocessing.Process(target=run, args=(send_end,)) |
|
59 |
process.start() |
|
60 |
process.join(waiting_time) |
|
61 | ||
62 |
if process.is_alive(): |
|
63 |
process.terminate() |
|
64 |
context = {k: v for k, v in data.items() if k != 'locators'} |
|
65 |
logger.error("Phantomjs process timeout, context : %s" % context) |
|
66 |
result = {'result': 'failure'} |
|
67 |
else: |
|
68 |
result = recv_end.recv() |
|
39 | 69 | |
40 |
stdout, stderr = phantom.communicate(json.dumps(data)) |
|
41 | ||
42 |
try: |
|
43 |
result = json.loads(stdout) |
|
44 |
except (ValueError,): |
|
45 |
result = {"result": "failure, couldn't decode JSON"} |
|
46 |
logger.error(stdout) |
|
47 | ||
48 |
# only kill process if it's still running |
|
49 |
if phantom.poll() is None: |
|
50 |
phantom.terminate() |
|
51 | ||
52 |
if result.get('stderr'): |
|
53 |
logger.warning(result['stderr']) |
|
54 | 70 |
return result |
55 | 71 | |
56 | 72 |
tests/settings.py | ||
---|---|---|
47 | 47 |
api_settings.user_settings.update({ |
48 | 48 |
'DEFAULT_AUTHENTICATION_CLASSES' : AUTHENTICATION_CLASSES, |
49 | 49 |
}) |
50 | ||
51 | ||
52 |
PHANTOMJS_WAITING_TIME = 0.25 |
tests/test_mandayejs.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 | |
3 | 3 |
import json |
4 |
import time |
|
4 | 5 |
import mock |
5 | 6 |
import pytest |
6 | 7 | |
... | ... | |
47 | 48 | |
48 | 49 | |
49 | 50 |
class MockedPopen(mock.Mock): |
51 |
stall_for = False |
|
50 | 52 | |
51 | 53 |
def communicate(self, data): |
54 |
if self.stall_for: |
|
55 |
time.sleep(13) |
|
52 | 56 |
return self.expected_output |
53 | 57 | |
54 | 58 | |
... | ... | |
272 | 276 |
assert result['url'] == 'https://whatever.com/someurl' |
273 | 277 | |
274 | 278 | |
279 |
@mock.patch('mandayejs.mandaye.utils.subprocess.Popen') |
|
280 |
def test_phantom_js_stalled_process(mocked_popen, caplog): |
|
281 |
mocked_popen.return_value = MockedPopen(expected_output=json.dumps({'whatever': 'whatever'}), stall_for=True) |
|
282 |
result = exec_phantom(LOGIN_INFO) |
|
283 | ||
284 |
for record in caplog.records(): |
|
285 |
assert record.levelname == 'ERROR' |
|
286 |
assert 'https://whatever.com' in record.message |
|
287 |
assert 'tenants/static/js/auth.checker.js' in record.message |
|
288 |
assert 'input[type=submit], button' in record.message |
|
289 | ||
290 |
assert result['result'] == 'failure' |
|
291 | ||
292 | ||
275 | 293 |
@mock.patch('mandayejs.applications.Test.SITE_LOCATORS', MOCKED_SITE_LOCATORS) |
276 | 294 |
def test_credentials_json_encoding(user_john): |
277 | 295 | |
278 |
- |