简体   繁体   English

释放virtualbox时Win32异常

[英]Win32 exception upon releasing virtualbox

I'm trying to run Virtualbox within a thread. 我正在尝试在线程中运行Virtualbox。 During the second iteration of the while loop, where the th variable gets reasigned, the app crashes and produces a Win32 exception. 在while循环的第二次迭代中,th变量被重新分配,应用程序崩溃并生成Win32异常。 This seems to be caused by the release of the vbox and session. 这似乎是由vbox和会话的发布引起的。 My question is how I do I properly release them manually? 我的问题是如何正确手动释放它们?

Win32 exception occurred releasing IUnknown at 0x035e40b8
Win32 exception occurred releasing IUnknown at 0x04babcb0

The basics of my application (virtualbox from pyvbox and virtualbox sdk) 我的应用程序的基础知识(来自pyvbox和virtualbox sdk的virtualbox)

import virtualbox
import threading
import time


class ThreadExecutor(threading.Thread):
    def __init__(self):
        self.vbox = None
        self.session = None
        self.vm = None
        super().__init__()

    def run(self):
        self.vbox = virtualbox.VirtualBox()
        self.session = virtualbox.Session()
        self.vm = self.vbox.find_machine("Ubuntu")
        self.vm.launch_vm_process(self.session, 'gui', '')

        time.sleep(30)
        if int(self.session.state) == 1:
            print('Boot failed!')
            return
        else:
            print('Powering down')
            self.session.console.power_down()
        print('Operation completed')
        return


if __name__ == '__main__':
    while True:
        print('Input')
        if input():
            th = ThreadExecutor()
            th.start()
            print('Thread started')

            time.sleep(5)
            while th.isAlive():
                print('App running')
                time.sleep(5)
            print('Execution finished')

To release the session reliable you should use a try/except/finally construction like this: 为了可靠地释放会话,您应该使用try / except / finally结构,如下所示:

try:
   #Your code
except:
   print("something unexpected happend")
finally:
   self.session.console.power_down()

I modified the code (without running it): 我修改了代码(没有运行它):

  • Fixing (stuff that wasn't right) and some reorganizing 修复(不正确的东西)和一些重组
  • Additional printing 附加印刷

in order to work and debug the issue (with no intention to fix it whatsoever - at least not at this stage). 为了解决问题并进行调试( 无意于对其进行任何修复 -至少不在此阶段)。

code.py : code.py

#!/usr/bin/env python3

import sys
import virtualbox
import threading
import time


DEFAULT_DEBUG_MSG_INDENT = "    "


def debug(text, indent_count, indent=DEFAULT_DEBUG_MSG_INDENT, leading_eoln_count=0):
    print("{:s}{:s}[TID: {:06d}]: {:s}".format("\n" * leading_eoln_count, indent * indent_count, threading.get_ident(), text))


class ThreadExecutor(threading.Thread):
    def __init__(self):
        super().__init__()
        self.vbox = virtualbox.VirtualBox()
        self.session = virtualbox.Session()
        if not self.vbox or not self.session:
            raise RuntimeError("virtualbox initialization failed")
        self.vm = self.vbox.find_machine("Ubuntu")
        if not self.vm:
            raise ValueError("VM not found")

    def run(self):
        start_wait_time = 15
        debug("Starting VM...", 1)
        self.vm.launch_vm_process(self.session, "gui", "")
        debug("Sleeping {:d} secs...".format(start_wait_time), 1)
        time.sleep(start_wait_time)
        if int(self.session.state) == 1:
            debug("Boot failed!", 1)
            return
        else:
            debug("Powering down", 1)
            self.session.console.power_down()
        debug("Operation completed", 1)


def run(threaded=True):
    debug("RUNNING with{:s} threads".format("" if threaded else "out"), 0, leading_eoln_count=1)
    sleep_time = 5
    while input("{:s}Press ANY key followed by ENTER to continue, ENTER ONLY to queet: ".format(DEFAULT_DEBUG_MSG_INDENT)):
        th = ThreadExecutor()
        if threaded:
            debug("Starting thread...", 0)
            th.start()
            debug("Thread started", 1)
            time.sleep(sleep_time)
            while th.isAlive():
                debug("App running", 1)
                time.sleep(sleep_time)
        else:
            debug("Running...", 0)
            th.run()
        debug("Execution finished", 1)
    debug("Done", 0)


def main():
    run(threaded=False)
    run()


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

and it worked!!! 而且有效!!!

Output : 输出

 (py35x64_test) e:\\Work\\Dev\\StackOverflow\\q051136288>"e:\\Work\\Dev\\VEnvs\\py35x64_test\\Scripts\\python.exe" code.py Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32 [TID: 036256]: RUNNING without threads Press ANY key followed by ENTER to continue, ENTER ONLY to queet: a [TID: 036256]: Running... [TID: 036256]: Starting VM... [TID: 036256]: Sleeping 15 secs... [TID: 036256]: Powering down [TID: 036256]: Operation completed [TID: 036256]: Execution finished Press ANY key followed by ENTER to continue, ENTER ONLY to queet: a [TID: 036256]: Running... [TID: 036256]: Starting VM... [TID: 036256]: Sleeping 15 secs... [TID: 036256]: Powering down [TID: 036256]: Operation completed [TID: 036256]: Execution finished Press ANY key followed by ENTER to continue, ENTER ONLY to queet: [TID: 036256]: Done [TID: 036256]: RUNNING with threads Press ANY key followed by ENTER to continue, ENTER ONLY to queet: a [TID: 036256]: Starting thread... [TID: 038520]: Starting VM... [TID: 036256]: Thread started [TID: 038520]: Sleeping 15 secs... [TID: 036256]: App running [TID: 036256]: App running [TID: 036256]: App running [TID: 038520]: Powering down [TID: 038520]: Operation completed [TID: 036256]: Execution finished Press ANY key followed by ENTER to continue, ENTER ONLY to queet: a [TID: 036256]: Starting thread... [TID: 028884]: Starting VM... [TID: 036256]: Thread started [TID: 028884]: Sleeping 15 secs... [TID: 036256]: App running [TID: 036256]: App running [TID: 036256]: App running [TID: 028884]: Powering down [TID: 028884]: Operation completed [TID: 036256]: Execution finished Press ANY key followed by ENTER to continue, ENTER ONLY to queet: [TID: 036256]: Done 

Original code was throwing (only relevant part): 原始代码被抛出(仅相关部分):

pywintypes.com_error: (-2147221008, 'CoInitialize has not been called.', None, None)

I suspected that moving virualbox init stuff in the initializer might be responsible for the behavior change (although as I was saying, I only moved the code because I considered the initializer the right place for it) - that was correct: moving the code back in run triggered the exception again. 我怀疑在初始化程序中移动virualbox init可能是行为更改的原因(尽管正如我所说,我只是移动了代码,因为我认为初始化程序是正确的位置)-正确:将代码移回运行再次触发异常。

After a brief inspection of virtualbox and vboxapi code, I think it has something to do with the place (thread) where CoInitializeEx takes place, but I can't put my finger on it. 在对virtualboxvboxapi代码进行了简短检查之后,我认为这与发生CoInitializeEx的位置(线程)有关,但是我无法动弹

I also tried to call the function manually ( pythoncom.CoInitializeEx(0) ) in the main block, but import pythoncom alone was triggering the exception to appear in the 1 st iteration. 我还尝试在主块中手动调用该函数( pythoncom.CoInitializeEx(0) ),但是仅import pythoncom会触发在第一次迭代中出现的异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM