On 19/11/2024 16.05, Daniel P. Berrangé wrote:
> Support the QEMU_TEST_QMP_BACKDOOR=backdoor.sock env variable as a
> way to get a QMP backdoor for debugging a stalled QEMU test. Most
> typically this would be used if running the tests directly:
>
> $ QEMU_TEST_QMP_BACKDOOR=backdoor.sock \
> QEMU_TEST_QEMU_BINARY=./build/qemu-system-arm \
> PYTHONPATH=./python \
> ./tests/functional/test_arm_tuxrun.py
>
> And then, when the test stalls, in a second shell run:
>
> $ ./scripts/qmp/qmp-shell backdoor.sock
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
> docs/devel/testing/functional.rst | 10 ++++++++++
> tests/functional/qemu_test/testcase.py | 7 +++++++
> 2 files changed, 17 insertions(+)
>
> diff --git a/docs/devel/testing/functional.rst b/docs/devel/testing/functional.rst
> index 6b5d0c5b98..b8ad7b0bf7 100644
> --- a/docs/devel/testing/functional.rst
> +++ b/docs/devel/testing/functional.rst
> @@ -176,6 +176,16 @@ primarily depend on the value of the ``qemu_bin`` class attribute.
> If it is not explicitly set by the test code, its default value will
> be the result the QEMU_TEST_QEMU_BINARY environment variable.
>
> +Debugging hung QEMU
> +^^^^^^^^^^^^^^^^^^^
> +
> +When test cases go wrong it may be helpful to debug a stalled QEMU
> +process. While the QEMUMachine class owns the primary QMP monitor
> +socket, it is possible to request a second QMP monitor be created
> +by setting the ``QEMU_TEST_QMP_BACKDOOR`` env variable to refer
> +to a UNIX socket name. The ``qmp-shell`` command can then be
> +attached to the stalled QEMU to examine its live state.
> +
> Attribute reference
> -------------------
>
> diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py
> index e2a329c3e5..eb889a5bae 100644
> --- a/tests/functional/qemu_test/testcase.py
> +++ b/tests/functional/qemu_test/testcase.py
> @@ -175,6 +175,13 @@ def _new_vm(self, name, *args):
> log_dir=self.logdir)
> self.log.debug('QEMUMachine "%s" created', name)
> self.log.debug('QEMUMachine "%s" temp_dir: %s', name, vm.temp_dir)
> +
> + if "QEMU_TEST_QMP_BACKDOOR" in os.environ:
> + path = os.environ["QEMU_TEST_QMP_BACKDOOR"]
Maybe slightly nicer to chech os.environ only once (and specify the
environment variable name only once):
path = os.environ.get('QEMU_TEST_QMP_BACKDOOR')
if path:
...
?
Thomas
> + vm.add_args("-chardev",
> + f"socket,id=backdoor,path={path},server=on,wait=off",
> + "-mon", "chardev=backdoor,mode=control")
> +
> if args:
> vm.add_args(*args)
> return vm