aboutsummaryrefslogtreecommitdiff
path: root/util/log.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/log.c')
-rw-r--r--util/log.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/util/log.c b/util/log.c
index 953a66b5a8..867264da8d 100644
--- a/util/log.c
+++ b/util/log.c
@@ -28,7 +28,7 @@
static char *logfilename;
static QemuMutex qemu_logfile_mutex;
-FILE *qemu_logfile;
+QemuLogFile *qemu_logfile;
int qemu_loglevel;
static int log_append = 0;
static GArray *debug_regions;
@@ -37,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. */
@@ -48,6 +52,7 @@ int qemu_log(const char *fmt, ...)
ret = 0;
}
}
+ rcu_read_unlock();
return ret;
}
@@ -56,12 +61,24 @@ 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;
@@ -79,43 +96,47 @@ void qemu_set_log(int log_flags)
}
qemu_mutex_lock(&qemu_logfile_mutex);
if (qemu_logfile && !need_to_open_file) {
- qemu_mutex_unlock(&qemu_logfile_mutex);
- qemu_log_close();
+ 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;
}
- qemu_mutex_unlock(&qemu_logfile_mutex);
+ atomic_rcu_set(&qemu_logfile, logfile);
}
+ qemu_mutex_unlock(&qemu_logfile_mutex);
}
void qemu_log_needs_buffers(void)
@@ -244,18 +265,27 @@ 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)
{
+ QemuLogFile *logfile;
+
qemu_mutex_lock(&qemu_logfile_mutex);
- if (qemu_logfile) {
- if (qemu_logfile != stderr) {
- fclose(qemu_logfile);
- }
- qemu_logfile = NULL;
+ logfile = qemu_logfile;
+
+ if (logfile) {
+ atomic_rcu_set(&qemu_logfile, NULL);
+ call_rcu(logfile, qemu_logfile_free, rcu);
}
qemu_mutex_unlock(&qemu_logfile_mutex);
}