diff options
Diffstat (limited to 'util/log.c')
| -rw-r--r-- | util/log.c | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/util/log.c b/util/log.c index c2198badf2..7837ff9917 100644 --- a/util/log.c +++ b/util/log.c @@ -45,7 +45,6 @@ static __thread FILE *thread_file; static __thread Notifier qemu_log_thread_cleanup_notifier; int qemu_loglevel; -static bool log_append; static bool log_per_thread; static GArray *debug_regions; @@ -80,13 +79,15 @@ static int log_thread_id(void) static void qemu_log_thread_cleanup(Notifier *n, void *unused) { - fclose(thread_file); - thread_file = NULL; + if (thread_file != stderr) { + fclose(thread_file); + thread_file = NULL; + } } /* Lock/unlock output. */ -FILE *qemu_log_trylock(void) +static FILE *qemu_log_trylock_with_err(Error **errp) { FILE *logfile; @@ -97,6 +98,9 @@ FILE *qemu_log_trylock(void) = g_strdup_printf(global_filename, log_thread_id()); logfile = fopen(filename, "w"); if (!logfile) { + error_setg_errno(errp, errno, + "Error opening logfile %s for thread %d", + filename, log_thread_id()); return NULL; } thread_file = logfile; @@ -123,6 +127,11 @@ FILE *qemu_log_trylock(void) return logfile; } +FILE *qemu_log_trylock(void) +{ + return qemu_log_trylock_with_err(NULL); +} + void qemu_log_unlock(FILE *logfile) { if (logfile) { @@ -266,40 +275,61 @@ static bool qemu_set_log_internal(const char *filename, bool changed_name, #endif qemu_loglevel = log_flags; - /* - * In all cases we only log if qemu_loglevel is set. - * Also: - * If per-thread, open the file for each thread in qemu_log_lock. - * If not daemonized we will always log either to stderr - * or to a file (if there is a filename). - * If we are daemonized, we will only log if there is a filename. - */ daemonized = is_daemonized(); - need_to_open_file = log_flags && !per_thread && (!daemonized || filename); + need_to_open_file = false; + if (!daemonized) { + /* + * If not daemonized we only log if qemu_loglevel is set, either to + * stderr or to a file (if there is a filename). + * If per-thread, open the file for each thread in qemu_log_trylock(). + */ + need_to_open_file = qemu_loglevel && !log_per_thread; + } else { + /* + * If we are daemonized, we will only log if there is a filename. + */ + need_to_open_file = filename != NULL; + } - if (logfile && (!need_to_open_file || changed_name)) { - qatomic_rcu_set(&global_file, NULL); - if (logfile != stderr) { + if (logfile) { + fflush(logfile); + if (changed_name && logfile != stderr) { RCUCloseFILE *r = g_new0(RCUCloseFILE, 1); r->fd = logfile; + qatomic_rcu_set(&global_file, NULL); call_rcu(r, rcu_close_file, rcu); + logfile = NULL; } - logfile = NULL; + } + + if (log_per_thread && daemonized) { + logfile = thread_file; } if (!logfile && need_to_open_file) { if (filename) { - logfile = fopen(filename, log_append ? "a" : "w"); - if (!logfile) { - error_setg_errno(errp, errno, "Error opening logfile %s", - filename); - return false; + if (log_per_thread) { + logfile = qemu_log_trylock_with_err(errp); + if (!logfile) { + return false; + } + qemu_log_unlock(logfile); + } else { + logfile = fopen(filename, "w"); + if (!logfile) { + error_setg_errno(errp, errno, "Error opening logfile %s", + filename); + return false; + } } /* In case we are a daemon redirect stderr to logfile */ if (daemonized) { dup2(fileno(logfile), STDERR_FILENO); fclose(logfile); - /* This will skip closing logfile in rcu_close_file. */ + /* + * This will skip closing logfile in rcu_close_file() + * or qemu_log_thread_cleanup(). + */ logfile = stderr; } } else { @@ -308,9 +338,11 @@ static bool qemu_set_log_internal(const char *filename, bool changed_name, logfile = stderr; } - log_append = 1; - - qatomic_rcu_set(&global_file, logfile); + if (log_per_thread && daemonized) { + thread_file = logfile; + } else { + qatomic_rcu_set(&global_file, logfile); + } } return true; } |