virtualbox-python icon indicating copy to clipboard operation
virtualbox-python copied to clipboard

Exception in event handler thread.

Open Elbert-Tardis opened this issue 5 years ago • 0 comments

ENVIRONMENT
  • Operating System: Windows 10 Pro (1903)
  • Python version: 3.7.2:
  • VirtualBox version: 6.1.4 r136177 (Qt5.6.2)
  • VirtualBox SDK version: 1.0
  • Location where VirtualBox SDK is installed: C:\Python3\python.exe (venv)
  • virtualbox-python / pyvbox version: 2.0.0
  • [x] Happens in latest master branch?
SUMMARY

When registering a callback function using the: register_on_machine_state_changed() function an exception occurs in the event monitor thread.

STEPS TO REPRODUCE

The following example reproduces the problem:

import virtualbox


def callback(event):
    print("Machine %s state changed to %s" % (event.machine_id, event.state))


vbox = virtualbox.VirtualBox()
vbox.register_on_machine_state_changed(callback)                       # Starts a thread which crashes in python 3.7 and VBox 6.1.4
session = virtualbox.Session()
machine = vbox.find_machine('<a machine>')
progress = machine.launch_vm_process(session, "gui", ''.encode())      # Workaround: use ''.encode() instead of just ''.
progress.wait_for_completion()
while True:
    pass
EXPECTED RESULTS

To see the state changes of the machine as it starts.

ACTUAL RESULTS
Unhanded exception in callback:
Traceback (most recent call last):
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\events.py", line 56, in _event_monitor
    callback(event_interface(event))
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 130, in __init__
    self._i = manager.cast_object(interface, self.__class__)._i
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\__init__.py", line 197, in cast_object
    i = self.manager.queryInterface(interface_object._i, name)
  File ".\test-virtualbox\venv-3\lib\site-packages\vboxapi\__init__.py", line 1082, in queryInterface
    return self.platform.queryInterface(oIUnknown, sClassName)
  File ".\test-virtualbox\venv-3\lib\site-packages\vboxapi\__init__.py", line 679, in queryInterface
    return CastTo(oIUnknown, sClassName)
  File ".\test-virtualbox\venv-3\lib\site-packages\win32com\client\__init__.py", line 141, in CastTo
    ob = gencache.EnsureDispatch(ob)
  File ".\test-virtualbox\venv-3\lib\site-packages\win32com\client\gencache.py", line 527, in EnsureDispatch
    disp = win32com.client.Dispatch(prog_id)
  File ".\test-virtualbox\venv-3\lib\site-packages\win32com\client\__init__.py", line 96, in Dispatch
    return __WrapDispatch(dispatch, userName, resultCLSID, typeinfo, clsctx=clsctx)
  File ".\test-virtualbox\venv-3\lib\site-packages\win32com\client\__init__.py", line 43, in __WrapDispatch
    return dynamic.Dispatch(dispatch, userName, WrapperClass, typeinfo, clsctx=clsctx)
  File ".\test-virtualbox\venv-3\lib\site-packages\win32com\client\dynamic.py", line 133, in Dispatch
    typeinfo = IDispatch.GetTypeInfo()
AttributeError: 'NoneType' object has no attribute 'GetTypeInfo'

Traceback (most recent call last):
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 201, in _call_method
    ret = method(*in_params)
  File ".\AppData\Local\Temp\gen_py\3.7\D7569351-1750-46F0-936E-BD127D5BC264x0x1x3.py", line 3398, in EventProcessed
    , aEvent)
pywintypes.com_error: (-2147417851, 'The server threw an exception.', None, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".\Python3\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\events.py", line 60, in _event_monitor
    event_source.event_processed(listener, event)
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library.py", line 30697, in event_processed
    in_p=[listener, event])
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 192, in _call
    return self._call_method(method, in_p=in_p)
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 214, in _call_method
    errobj.msg = exc.args[2][2]
TypeError: 'NoneType' object is not subscriptable
Exception in thread Thread-6:
Traceback (most recent call last):
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 201, in _call_method
    ret = method(*in_params)
  File ".\AppData\Local\Temp\gen_py\3.7\D7569351-1750-46F0-936E-BD127D5BC264x0x1x3.py", line 3398, in EventProcessed
    , aEvent)
pywintypes.com_error: (-2147417851, 'The server threw an exception.', None, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ".\Python3\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File ".\Python3\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\events.py", line 60, in _event_monitor
    event_source.event_processed(listener, event)
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library.py", line 30697, in event_processed
    in_p=[listener, event])
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 192, in _call
    return self._call_method(method, in_p=in_p)
  File ".\test-virtualbox\venv-3\lib\site-packages\virtualbox\library_base.py", line 214, in _call_method
    errobj.msg = exc.args[2][2]
TypeError: 'NoneType' object is not subscriptable
ANALYSIS

The event monitor thread contains the following code:

def _event_monitor(callback, event_source, listener, event_interface, quit):
    global _callbacks
    try:
        while not quit.is_set():
            try:
                event = event_source.get_event(listener, 1000)
            except library.VBoxError:
                print("Unregistering %s due to VBoxError on get_event" %
                      listener, file=sys.stderr)
                break
            if event:       <====
                ...
                ...

The Truth value testing for 'event' is implemented in the base class of the IEvent class (Interface). The code is:

def __nonzero__(self):
    return bool(self._i)

However, in python 3 the function __bool__() has to be implemented for Truth testing.

PROPOSED SOLUTION

Add the following assignment after the above function in: .\Lib\site-packages\virtualbox\library_base.py

__bool__ = __nonzero__

Elbert-Tardis avatar Mar 17 '20 09:03 Elbert-Tardis