1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-11-24 17:28:08 +00:00

Fix a crash with Python 3.4 when you stop IOU

http://bugs.python.org/issue23140
This commit is contained in:
Julien Duponchelle 2015-02-26 11:29:57 +01:00
parent aa40e6097e
commit 5a58f6efc8
3 changed files with 48 additions and 8 deletions

View File

@ -483,18 +483,19 @@ class IOUVM(BaseVM):
self._ioucon_thread = None self._ioucon_thread = None
self._terminate_process_iou() self._terminate_process_iou()
try: if self._iou_process.returncode is None:
yield from asyncio.wait_for(self._iou_process.wait(), timeout=3) try:
except asyncio.TimeoutError: yield from gns3server.utils.asyncio.wait_for_process_termination(self._iou_process, timeout=3)
self._iou_process.kill() except asyncio.TimeoutError:
if self._iou_process.returncode is None: self._iou_process.kill()
log.warn("IOU process {} is still running".format(self._iou_process.pid)) if self._iou_process.returncode is None:
log.warn("IOU process {} is still running".format(self._iou_process.pid))
self._iou_process = None self._iou_process = None
if self._iouyap_process is not None: if self._iouyap_process is not None:
self._terminate_process_iouyap() self._terminate_process_iouyap()
try: try:
yield from asyncio.wait_for(self._iouyap_process.wait(), timeout=3) yield from gns3server.utils.asyncio.wait_for_process_termination(self._iouyap_process, timeout=3)
except asyncio.TimeoutError: except asyncio.TimeoutError:
self._iouyap_process.kill() self._iouyap_process.kill()
if self._iouyap_process.returncode is None: if self._iouyap_process.returncode is None:

View File

@ -53,3 +53,27 @@ def subprocess_check_output(*args, cwd=None, env=None):
if output is None: if output is None:
return "" return ""
return output.decode("utf-8") return output.decode("utf-8")
@asyncio.coroutine
def wait_for_process_termination(process, timeout=10):
"""
Wait for a process terminate, and raise asyncio.TimeoutError in case of
timeout.
In theory this can be implemented by just:
yield from asyncio.wait_for(self._iou_process.wait(), timeout=100)
But it's broken before Python 3.4:
http://bugs.python.org/issue23140
:param process: An asyncio subprocess
:param timeout: Timeout in seconds
"""
while timeout > 0:
if process.returncode is not None:
return
yield from asyncio.sleep(0.1)
timeout -= 0.1
raise asyncio.TimeoutError()

View File

@ -18,8 +18,9 @@
import asyncio import asyncio
import pytest import pytest
from unittest.mock import MagicMock
from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_output from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_output, wait_for_process_termination
def test_wait_run_in_executor(loop): def test_wait_run_in_executor(loop):
@ -50,3 +51,17 @@ def test_subprocess_check_output(loop, tmpdir, restore_original_path):
exec = subprocess_check_output("cat", path) exec = subprocess_check_output("cat", path)
result = loop.run_until_complete(asyncio.async(exec)) result = loop.run_until_complete(asyncio.async(exec))
assert result == "TEST" assert result == "TEST"
def test_wait_for_process_termination(loop):
process = MagicMock()
process.returncode = 0
exec = wait_for_process_termination(process)
loop.run_until_complete(asyncio.async(exec))
process = MagicMock()
process.returncode = None
exec = wait_for_process_termination(process, timeout=0.5)
with pytest.raises(asyncio.TimeoutError):
loop.run_until_complete(asyncio.async(exec))