mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-01 04:38:12 +00:00
Fix a lock issue with some virtualbox vm
Fix https://github.com/GNS3/gns3-gui/issues/1444
This commit is contained in:
parent
042a69eecf
commit
0eafb6f06c
@ -30,7 +30,7 @@ import asyncio
|
|||||||
|
|
||||||
from gns3server.utils import parse_version
|
from gns3server.utils import parse_version
|
||||||
from gns3server.utils.telnet_server import TelnetServer
|
from gns3server.utils.telnet_server import TelnetServer
|
||||||
from gns3server.utils.asyncio import wait_for_file_creation, wait_for_named_pipe_creation
|
from gns3server.utils.asyncio import wait_for_file_creation, wait_for_named_pipe_creation, locked_coroutine
|
||||||
from .virtualbox_error import VirtualBoxError
|
from .virtualbox_error import VirtualBoxError
|
||||||
from ..nios.nio_udp import NIOUDP
|
from ..nios.nio_udp import NIOUDP
|
||||||
from ..nios.nio_nat import NIONAT
|
from ..nios.nio_nat import NIONAT
|
||||||
@ -230,7 +230,7 @@ class VirtualBoxVM(BaseVM):
|
|||||||
if (yield from self.check_hw_virtualization()):
|
if (yield from self.check_hw_virtualization()):
|
||||||
self._hw_virtualization = True
|
self._hw_virtualization = True
|
||||||
|
|
||||||
@asyncio.coroutine
|
@locked_coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
Stops this VirtualBox VM.
|
Stops this VirtualBox VM.
|
||||||
|
@ -127,3 +127,24 @@ def wait_for_named_pipe_creation(pipe_path, timeout=60):
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
raise asyncio.TimeoutError()
|
raise asyncio.TimeoutError()
|
||||||
|
|
||||||
|
|
||||||
|
def locked_coroutine(f):
|
||||||
|
"""
|
||||||
|
Method decorator that replace asyncio.coroutine that warranty
|
||||||
|
that this specific method of this class instance will not we
|
||||||
|
executed twice at the same time
|
||||||
|
"""
|
||||||
|
@asyncio.coroutine
|
||||||
|
def new_function(*args, **kwargs):
|
||||||
|
|
||||||
|
# In the instance of the class we will store
|
||||||
|
# a lock has an attribute.
|
||||||
|
lock_var_name = "__" + f.__name__ + "_lock"
|
||||||
|
if not hasattr(args[0], lock_var_name):
|
||||||
|
setattr(args[0], lock_var_name, asyncio.Lock())
|
||||||
|
|
||||||
|
with (yield from getattr(args[0], lock_var_name)):
|
||||||
|
return (yield from f(*args, **kwargs))
|
||||||
|
|
||||||
|
return new_function
|
||||||
|
@ -21,7 +21,7 @@ import pytest
|
|||||||
import sys
|
import sys
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_output, wait_for_process_termination
|
from gns3server.utils.asyncio import wait_run_in_executor, subprocess_check_output, wait_for_process_termination, locked_coroutine
|
||||||
|
|
||||||
|
|
||||||
def test_wait_run_in_executor(loop):
|
def test_wait_run_in_executor(loop):
|
||||||
@ -67,3 +67,26 @@ def test_wait_for_process_termination(loop):
|
|||||||
exec = wait_for_process_termination(process, timeout=0.5)
|
exec = wait_for_process_termination(process, timeout=0.5)
|
||||||
with pytest.raises(asyncio.TimeoutError):
|
with pytest.raises(asyncio.TimeoutError):
|
||||||
loop.run_until_complete(asyncio.async(exec))
|
loop.run_until_complete(asyncio.async(exec))
|
||||||
|
|
||||||
|
|
||||||
|
def test_lock_decorator(loop):
|
||||||
|
"""
|
||||||
|
The test check if the the second call to method_to_lock wait for the
|
||||||
|
first call to finish
|
||||||
|
"""
|
||||||
|
|
||||||
|
class TestLock:
|
||||||
|
def __init__(self):
|
||||||
|
self._test_val = 0
|
||||||
|
|
||||||
|
@locked_coroutine
|
||||||
|
def method_to_lock(self):
|
||||||
|
res = self._test_val
|
||||||
|
yield from asyncio.sleep(0.1)
|
||||||
|
self._test_val += 1
|
||||||
|
return res
|
||||||
|
|
||||||
|
i = TestLock()
|
||||||
|
res = set(loop.run_until_complete(asyncio.gather(i.method_to_lock(), i.method_to_lock())))
|
||||||
|
assert res == set((0, 1,)) # We use a set to test this to avoid order issue
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user