aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-12-20 14:00:49 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-12-20 14:00:49 +0000
commitf59b31e6d0c69792b5d817c5aa0a6ed64fba42e0 (patch)
treeae26a62aaa277acb511a99d209b0c82c5e50b03d /util
parent8e5943260a8f765216674ee87ce8588cc4e7463e (diff)
parent380976f40f909b735acb60d5d424de7eb1b7107e (diff)
Merge remote-tracking branch 'remotes/stsquad/tags/pull-tesing-and-misc-191219-1' into staging
Various testing and logging updates - test tci with Travis - enable multiarch testing in Travis - default to out-of-tree builds - make changing logfile safe via RCU - remove redundant tests - remove gtester test from docker - convert DEBUG_MMAP to tracepoints - remove hand rolled glob function - trigger tcg re-configure when needed # gpg: Signature made Thu 19 Dec 2019 08:24:08 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-tesing-and-misc-191219-1: (25 commits) tests/tcg: ensure we re-configure if configure.sh is updated trace: replace hand-crafted pattern_glob with g_pattern_match_simple linux-user: convert target_munmap debug to a tracepoint linux-user: log page table changes under -d page linux-user: add target_mmap_complete tracepoint linux-user: convert target_mmap debug to tracepoint linux-user: convert target_mprotect debug to tracepoint travis.yml: Remove the redundant clang-with-MAIN_SOFTMMU_TARGETS entry docker: gtester is no longer used Added tests for close and change of logfile. Add use of RCU for qemu_logfile. qemu_log_lock/unlock now preserves the qemu_logfile handle. Add a mutex to guarantee single writer to qemu_logfile handle. Cleaned up flow of code in qemu_set_log(), to simplify and clarify. Fix double free issue in qemu_set_log_filename(). ci: build out-of-tree travis.yml: Enable builds on arm64, ppc64le and s390x tests/test-util-filemonitor: Skip test on non-x86 Travis containers tests/hd-geo-test: Skip test when images can not be created iotests: Skip test 079 if it is not possible to create large files ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util')
-rw-r--r--util/log.c100
1 files changed, 76 insertions, 24 deletions
diff --git a/util/log.c b/util/log.c
index 1ca13059ee..867264da8d 100644
--- a/util/log.c
+++ b/util/log.c
@@ -24,9 +24,11 @@
#include "qapi/error.h"
#include "qemu/cutils.h"
#include "trace/control.h"
+#include "qemu/thread.h"
static char *logfilename;
-FILE *qemu_logfile;
+static QemuMutex qemu_logfile_mutex;
+QemuLogFile *qemu_logfile;
int qemu_loglevel;
static int log_append = 0;
static GArray *debug_regions;
@@ -35,10 +37,14 @@ static GArray *debug_regions;
int qemu_log(const char *fmt, ...)
{
int ret = 0;
- if (qemu_logfile) {
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
va_list ap;
va_start(ap, fmt);
- ret = vfprintf(qemu_logfile, fmt, ap);
+ ret = vfprintf(logfile->fd, fmt, ap);
va_end(ap);
/* Don't pass back error results. */
@@ -46,57 +52,91 @@ int qemu_log(const char *fmt, ...)
ret = 0;
}
}
+ rcu_read_unlock();
return ret;
}
+static void __attribute__((__constructor__)) qemu_logfile_init(void)
+{
+ qemu_mutex_init(&qemu_logfile_mutex);
+}
+
+static void qemu_logfile_free(QemuLogFile *logfile)
+{
+ g_assert(logfile);
+
+ if (logfile->fd != stderr) {
+ fclose(logfile->fd);
+ }
+ g_free(logfile);
+}
+
static bool log_uses_own_buffers;
/* enable or disable low levels log */
void qemu_set_log(int log_flags)
{
+ bool need_to_open_file = false;
+ QemuLogFile *logfile;
+
qemu_loglevel = log_flags;
#ifdef CONFIG_TRACE_LOG
qemu_loglevel |= LOG_TRACE;
#endif
- if (!qemu_logfile &&
- (is_daemonized() ? logfilename != NULL : qemu_loglevel)) {
+ /*
+ * In all cases we only log if qemu_loglevel is set.
+ * Also:
+ * If not daemonized we will always log either to stderr
+ * or to a file (if there is a logfilename).
+ * If we are daemonized,
+ * we will only log if there is a logfilename.
+ */
+ if (qemu_loglevel && (!is_daemonized() || logfilename)) {
+ need_to_open_file = true;
+ }
+ qemu_mutex_lock(&qemu_logfile_mutex);
+ if (qemu_logfile && !need_to_open_file) {
+ logfile = qemu_logfile;
+ atomic_rcu_set(&qemu_logfile, NULL);
+ call_rcu(logfile, qemu_logfile_free, rcu);
+ } else if (!qemu_logfile && need_to_open_file) {
+ logfile = g_new0(QemuLogFile, 1);
if (logfilename) {
- qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
- if (!qemu_logfile) {
+ logfile->fd = fopen(logfilename, log_append ? "a" : "w");
+ if (!logfile->fd) {
+ g_free(logfile);
perror(logfilename);
_exit(1);
}
/* In case we are a daemon redirect stderr to logfile */
if (is_daemonized()) {
- dup2(fileno(qemu_logfile), STDERR_FILENO);
- fclose(qemu_logfile);
+ dup2(fileno(logfile->fd), STDERR_FILENO);
+ fclose(logfile->fd);
/* This will skip closing logfile in qemu_log_close() */
- qemu_logfile = stderr;
+ logfile->fd = stderr;
}
} else {
/* Default to stderr if no log file specified */
assert(!is_daemonized());
- qemu_logfile = stderr;
+ logfile->fd = stderr;
}
/* must avoid mmap() usage of glibc by setting a buffer "by hand" */
if (log_uses_own_buffers) {
static char logfile_buf[4096];
- setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
+ setvbuf(logfile->fd, logfile_buf, _IOLBF, sizeof(logfile_buf));
} else {
#if defined(_WIN32)
/* Win32 doesn't support line-buffering, so use unbuffered output. */
- setvbuf(qemu_logfile, NULL, _IONBF, 0);
+ setvbuf(logfile->fd, NULL, _IONBF, 0);
#else
- setvbuf(qemu_logfile, NULL, _IOLBF, 0);
+ setvbuf(logfile->fd, NULL, _IOLBF, 0);
#endif
log_append = 1;
}
+ atomic_rcu_set(&qemu_logfile, logfile);
}
- if (qemu_logfile &&
- (is_daemonized() ? logfilename == NULL : !qemu_loglevel)) {
- qemu_log_close();
- }
+ qemu_mutex_unlock(&qemu_logfile_mutex);
}
void qemu_log_needs_buffers(void)
@@ -113,6 +153,7 @@ void qemu_set_log_filename(const char *filename, Error **errp)
{
char *pidstr;
g_free(logfilename);
+ logfilename = NULL;
pidstr = strstr(filename, "%");
if (pidstr) {
@@ -224,18 +265,29 @@ out:
/* fflush() the log file */
void qemu_log_flush(void)
{
- fflush(qemu_logfile);
+ QemuLogFile *logfile;
+
+ rcu_read_lock();
+ logfile = atomic_rcu_read(&qemu_logfile);
+ if (logfile) {
+ fflush(logfile->fd);
+ }
+ rcu_read_unlock();
}
/* Close the log file */
void qemu_log_close(void)
{
- if (qemu_logfile) {
- if (qemu_logfile != stderr) {
- fclose(qemu_logfile);
- }
- qemu_logfile = NULL;
+ QemuLogFile *logfile;
+
+ qemu_mutex_lock(&qemu_logfile_mutex);
+ logfile = qemu_logfile;
+
+ if (logfile) {
+ atomic_rcu_set(&qemu_logfile, NULL);
+ call_rcu(logfile, qemu_logfile_free, rcu);
}
+ qemu_mutex_unlock(&qemu_logfile_mutex);
}
const QEMULogItem qemu_log_items[] = {