
On Mon, Sep 12, 2016 at 02:12:10PM +0300, Nikolay Shirokovskiy wrote:
Read API call of logger daemon is used to get extra information from terminated qemu process. For this purpose we need to wait until qemu process finishes its writing to log. We need to:
1. Read until EOF. 2. Don't stop reading on hangup.
virtlogd will not receive EOF as both qemu and libvirtd keep logging pipe descriptor. Thus let's close it after qemu process startup is finished as it will not be used anymore. All following logging on behalf of qemu by libvirt is done either thru daemon API or by receiving new writing descriptor.
Beware, qemuDomainLogContextFree is unref actually. --- src/logging/log_handler.c | 39 +++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.c | 4 ++++ src/qemu/qemu_domain.h | 1 + src/qemu/qemu_process.c | 2 ++ 4 files changed, 44 insertions(+), 2 deletions(-)
Any virtlogd changes should really be in separate commits from any QEMU changes. virtlogd is intended to be a reusable component of libvirt for multiple use cases, so any changes to it need to described & justifiable independently of any QEMU changes.
+static virLogHandlerLogFilePtr +virLogHandlerGetLogFileFromPath(virLogHandlerPtr handler, + const char* path) +{ + size_t i; + + for (i = 0; i < handler->nfiles; i++) { + if (STREQ(handler->files[i]->path, path)) + return handler->files[i]; + } + + return NULL; +}
@@ -167,11 +185,14 @@ virLogHandlerDomainLogFileEvent(int watch, goto error; }
+ if (len == 0) + goto error; + if (virRotatingFileWriterAppend(logfile->file, buf, len) != len) goto error;
if (events & VIR_EVENT_HANDLE_HANGUP) - goto error; + goto reread;
This patch hunk seems to be indendant of the other changes in this file. It is a straightfoward bugfix to ensure we full read all data before handling the hangup. So it should be a separate commit too.
virObjectUnlock(handler); return; @@ -179,6 +200,7 @@ virLogHandlerDomainLogFileEvent(int watch, error: handler->inhibitor(false, handler->opaque); virLogHandlerLogFileClose(handler, logfile); + virCondBroadcast(&handler->condition); virObjectUnlock(handler); }
@@ -198,6 +220,9 @@ virLogHandlerNew(bool privileged, if (!(handler = virObjectLockableNew(virLogHandlerClass))) goto error;
+ if (virCondInit(&handler->condition) < 0) + goto error; + handler->privileged = privileged; handler->max_size = max_size; handler->max_backups = max_backups; @@ -357,6 +382,7 @@ virLogHandlerDispose(void *obj) virLogHandlerLogFileFree(handler->files[i]); } VIR_FREE(handler->files); + virCondDestroy(&handler->condition); }
@@ -401,7 +427,8 @@ virLogHandlerDomainOpenLogFile(virLogHandlerPtr handler, pipefd[0] = -1; memcpy(file->domuuid, domuuid, VIR_UUID_BUFLEN); if (VIR_STRDUP(file->driver, driver) < 0 || - VIR_STRDUP(file->domname, domname) < 0) + VIR_STRDUP(file->domname, domname) < 0 || + VIR_STRDUP(file->path, path) < 0) goto error;
if ((file->file = virRotatingFileWriterNew(path, @@ -496,6 +523,14 @@ virLogHandlerDomainReadLogFile(virLogHandlerPtr handler,
virObjectLock(handler);
+ while (virLogHandlerGetLogFileFromPath(handler, path)) { + if (virCondWait(&handler->condition, &handler->parent.lock) < 0) { + virReportSystemError(errno, "%s", + _("failed to wait for EOF")); + goto error; + } + }
Ewww no - this code is not only intended for use from codepath where QEMU is shutdown. It absolutely should be able to read from a log where QEMU is still running. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|