[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v3 2/3] qemu.py: include debug information on la
From: |
Amador Pahim |
Subject: |
Re: [Qemu-devel] [PATCH v3 2/3] qemu.py: include debug information on launch error |
Date: |
Thu, 20 Jul 2017 17:50:54 +0200 |
On Thu, Jul 20, 2017 at 5:01 PM, Markus Armbruster <address@hidden> wrote:
> Amador Pahim <address@hidden> writes:
>
>> On Thu, Jul 20, 2017 at 1:58 PM, Markus Armbruster <address@hidden> wrote:
>>> Amador Pahim <address@hidden> writes:
>>>
>>>> When launching a VM, if an exception happens and the VM is not
>>>> initiated, it is useful to see the qemu command line that was executed
>>>> and the output of that command.
>>>>
>>>> Before the patch:
>>>>
>>>> >>> VM = qemu.QEMUMachine('../aarch64-softmmu/qemu-system-aarch64')
>>>> >>> VM.launch()
>>>> Traceback (most recent call last):
>>>> File "<stdin>", line 1, in <module>
>>>> File "qemu.py", line 137, in launch
>>>> self._post_launch()
>>>> File "qemu.py", line 121, in _post_launch
>>>> self._qmp.accept()
>>>> File "qmp/qmp.py", line 145, in accept
>>>> self.__sock, _ = self.__sock.accept()
>>>> File "/usr/lib64/python2.7/socket.py", line 206, in accept
>>>> sock, addr = self._sock.accept()
>>>> socket.timeout: timed out
>>>>
>>>> After the patch:
>>>>
>>>> >>> VM = qemu.QEMUMachine('../aarch64-softmmu/qemu-system-aarch64')
>>>> >>> VM.launch()
>>>> Traceback (most recent call last):
>>>> File "<stdin>", line 1, in <module>
>>>> File "qemu.py", line 156, in launch
>>>> raise RuntimeError(msg)
>>>> RuntimeError: Error launching VM.
>>>> Original Exception:
>>>> Traceback (most recent call last):
>>>> File "qemu.py", line 138, in launch
>>>> self._post_launch()
>>>> File "qemu.py", line 122, in _post_launch
>>>> self._qmp.accept()
>>>> File "qmp/qmp.py", line 145, in accept
>>>> self.__sock, _ = self.__sock.accept()
>>>> File "/usr/lib64/python2.7/socket.py", line 206, in accept
>>>> sock, addr = self._sock.accept()
>>>> timeout: timed out
>>>> Command:
>>>> /usr/bin/qemu-system-aarch64 -chardev socket,id=mon,
>>>> path=/var/tmp/qemu-23958-monitor.sock -mon chardev=mon,mode=control
>>>> -display none -vga none
>>>> Output:
>>>> qemu-system-aarch64: No machine specified, and there is no default
>>>> Use -machine help to list supported machines
>>>>
>>>> Also, if the launch() faces an exception, the 'except' now will use args
>>>> to fill the debug information. So this patch assigns 'args' earlier,
>>>> assuring it will be available for the 'except'.
>>>>
>>>> Signed-off-by: Amador Pahim <address@hidden>
>>>> Reviewed-by: Fam Zheng <address@hidden>
>>>> ---
>>>> scripts/qemu.py | 18 ++++++++++++++++--
>>>> 1 file changed, 16 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/scripts/qemu.py b/scripts/qemu.py
>>>> index f0fade32bd..2707ae7f75 100644
>>>> --- a/scripts/qemu.py
>>>> +++ b/scripts/qemu.py
>>>> @@ -18,6 +18,7 @@ import os
>>>> import sys
>>>> import subprocess
>>>> import qmp.qmp
>>>> +import traceback
>>>>
>>>>
>>>> class QEMUMachine(object):
>>>> @@ -129,17 +130,30 @@ class QEMUMachine(object):
>>>> '''Launch the VM and establish a QMP connection'''
>>>> devnull = open('/dev/null', 'rb')
>>>> qemulog = open(self._qemu_log_path, 'wb')
>>>> + args = self._wrapper + [self._binary] + self._base_args() +
>>>> self.args
>>>> try:
>>>> self._pre_launch()
>>>> - args = self._wrapper + [self._binary] + self._base_args() +
>>>> self._args
>>>> self._popen = subprocess.Popen(args, stdin=devnull,
>>>> stdout=qemulog,
>>>> stderr=subprocess.STDOUT,
>>>> shell=False)
>>>> self._post_launch()
>>>
>>> Lifting the assignment out of the try makes sense, because exceptions
>>> there are programming errors.
>>>
>>> Why are ._pre_launch() and ._post_launch() inside the try?
>>
>> The _pre_launch()/_post_launch() are probably the main source of
>> exceptions here and I assume we want to handle the exceptions coming
>> from them.
>>
>> The call to subprocess.Popen() is unlikely to raise exceptions. I
>> mean, it's easy to trigger an 'OSError' exception providing a
>> non-existent command to Popen, but once we provide something
>> executable, we will not see an exception here if the command fails.
>> The CalledProcessError is only raised by subprocess.check_call() or
>> subprocess.check_output().
>
> Okay.
>
> Catching all exceptions is too sloppy for my taste. But it's not your
> patch's fault.
>
>>>> except:
>>>
>>> Why do we catch all exceptions, and not just
>>> subprocess.CalledProcessError?
>>>
>>>> + self._load_io_log()
>>>> if self.is_running():
>>>
>>> I suspect we can't get here only for "odd" exceptions, not for
>>> subprocess.CalledProcessError.
>>>
>>>> self._popen.kill()
>>>> self._popen.wait()
>>>> - self._load_io_log()
>>>> + else:
>>>> + exc_type, exc_value, exc_traceback = sys.exc_info()
>>>> + msg = ('Error launching VM.\n'
>>>> + 'Original Exception: \n%s'
>>>> + 'Command:\n%s\n'
>>>> + 'Output:\n%s\n' %
>>>> + (''.join(traceback.format_exception(exc_type,
>>>> + exc_value,
>>>> +
>>>> exc_traceback)),
>>>> + ' '.join(args),
>>>> + self._iolog))
>>>> + self._post_shutdown()
>>>> + raise RuntimeError(msg)
>>>> self._post_shutdown()
>>>> raise
>>>
>>> Why do we print a traceback when subprocess.CalledProcessError?
>>
>> subprocess.CalledProcessError will not happen with subprocess.Popen,
>> even if the command fails. But if the virtual machine does not start,
>> we will, for example, see a 'socket.timeout' exception coming from
>> _post_launch() when it tries to connect to the qemu monitor.
>
> A traceback is a inexcusably lazy way to report such errors. You're
> putting lipstick on a pig.
>
> When putting on lipstick is all we can do, it can be better than
> nothing. Is it all we can do?
Ok, so let me take this opportunity to cleanup this code at once.
- Re: [Qemu-devel] [PATCH v3 1/3] qemu.py: fix is_running(), (continued)
[Qemu-devel] [PATCH v3 2/3] qemu.py: include debug information on launch error, Amador Pahim, 2017/07/20
[Qemu-devel] [PATCH v3 3/3] qemu.py: make 'args' public, Amador Pahim, 2017/07/20