[libvirt] [PATCH 3/4] qemu: monitor: Produce better errors on monitor hangup
Ján Tomko
jtomko at redhat.com
Tue Sep 24 12:19:44 UTC 2013
On 09/19/2013 11:23 AM, Peter Krempa wrote:
> Change the monitor error code to add the ability to access the qemu log
> file using a file descriptor so that we can dig in it for a more useful
> error message. The error is now logged on monitor hangups and overwrites
> a possible lesser error. A hangup on the monitor usualy means that qemu
> has crashed and there's a significant chance it produced a useful error
> message.
>
> The functionality will be latent until the next patch.
> ---
> src/qemu/qemu_monitor.c | 70 ++++++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 64 insertions(+), 6 deletions(-)
>
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index c3701fe..5369975 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -32,6 +32,8 @@
> #include "qemu_monitor.h"
> #include "qemu_monitor_text.h"
> #include "qemu_monitor_json.h"
> +#include "qemu_domain.h"
> +#include "qemu_process.h"
> #include "virerror.h"
> #include "viralloc.h"
> #include "virlog.h"
> @@ -331,6 +333,37 @@ qemuMonitorOpenPty(const char *monitor)
> }
>
>
> +/* Get a possible error from qemu's log. This function closes the
> + * corresponding log fd */
> +static char *
> +qemuMonitorGetErrorFromLog(qemuMonitorPtr mon)
> +{
> + int len;
> + char *logbuf = NULL;
> + int orig_errno = errno;
> +
> + if (mon->logfd < 0)
> + return NULL;
> +
> + if (VIR_ALLOC_N(logbuf, 4096) < 0)
> + goto error;
> +
> + if ((len = qemuProcessReadLog(mon->logfd, logbuf, 4096 - 1, 0, true)) <= 0)
> + goto error;
> +
> + errno = orig_errno;
> + VIR_FORCE_CLOSE(mon->logfd);
> + return logbuf;
> +
> +error:
> + virResetLastError();
What error is this resetting? qemuProcessReadLog doesn't set any and you can
use VIR_ALLOC_N_QUIET for the other one.
> + VIR_FREE(logbuf);
> + VIR_FORCE_CLOSE(mon->logfd);
> + errno = orig_errno;
> + return NULL;
> +}
> +
> +
> /* This method processes data that has been received
> * from the monitor. Looking for async events and
> * replies/errors.
> @@ -564,6 +597,7 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
> qemuMonitorPtr mon = opaque;
> bool error = false;
> bool eof = false;
> + bool hangup = false;
>
> virObjectRef(mon);
>
> @@ -614,12 +648,14 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
> }
> }
>
> - if (!error &&
> - events & VIR_EVENT_HANDLE_HANGUP) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("End of file from monitor"));
> - eof = true;
> - events &= ~VIR_EVENT_HANDLE_HANGUP;
> + if (events & VIR_EVENT_HANDLE_HANGUP) {
> + hangup = true;
> + if (!error) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("End of file from monitor"));
> + eof = true;
> + events &= ~VIR_EVENT_HANDLE_HANGUP;
> + }
> }
>
> if (!error && !eof &&
> @@ -638,6 +674,28 @@ qemuMonitorIO(int watch, int fd, int events, void *opaque) {
> }
>
> if (error || eof) {
> + if (hangup) {
> + /* Check if an error message from qemu is available and if so, use
> + * it to overwrite the actual message. It's done only on early
*in
> + * startup phases where the message from qemu is certailny more
*certainly
> + * interresting than a "connection reset by peer" message.
*interesting
> + */
> + char *qemuMessage;
> +
> + if ((qemuMessage = qemuMonitorGetErrorFromLog(mon)) &&
> + strlen(qemuMessage) > 0) {
qemuMonitorGetErrorFromLog returns NULL when nothing was read, strlen should
not be necessary.
> +
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("early end of file from monitor: "
> + "possible problem:\n%s"),
> + qemuMessage);
> + virCopyLastError(&mon->lastError);
> + virResetLastError();
> + }
> +
> + VIR_FREE(qemuMessage);
> + }
> +
> if (mon->lastError.code != VIR_ERR_OK) {
> /* Already have an error, so clear any new error */
> virResetLastError();
>
Jan
More information about the libvir-list
mailing list