Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=9d6a1843fefe07... Commit: 9d6a1843fefe0799065afbe5d0a7637fed6887fc Parent: 2f05327bd8e7a072418dca45988ab5a814109258 Author: Christine Caulfield ccaulfie@redhat.com AuthorDate: Thu Oct 30 09:43:35 2014 +0000 Committer: Christine Caulfield ccaulfie@redhat.com CommitterDate: Thu Oct 30 09:43:35 2014 +0000
liblogthread: Avoid potetntial race when changing log files
There is a potential for a crash when a log file is changed or re-opened as the fclose can happen in the main thread while the writing thread is about to output data.
This patch avoids that by allocating a new fp for the new file and only closing the old fp* later one when the thread holds the lock.
Signed-off-by: Christine Caulfield ccaulfie@redhat.com --- common/liblogthread/liblogthread.c | 36 +++++++++++++++++++++++++++--------- 1 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/common/liblogthread/liblogthread.c b/common/liblogthread/liblogthread.c index 088d171..b44f01a 100644 --- a/common/liblogthread/liblogthread.c +++ b/common/liblogthread/liblogthread.c @@ -38,6 +38,7 @@ static int logt_logfile_priority; static char logt_name[PATH_MAX]; static char logt_logfile[PATH_MAX]; static FILE *logt_logfile_fp; +static FILE *new_logt_logfile_fp;
static char *_time(time_t *t) { @@ -100,6 +101,13 @@ static void *thread_fn(void *arg)
prev_dropped = dropped; dropped = 0; + + if (new_logt_logfile_fp) { + fclose(logt_logfile_fp); + logt_logfile_fp = new_logt_logfile_fp; + new_logt_logfile_fp = NULL; + } + pthread_mutex_unlock(&mutex);
if (prev_dropped) { @@ -176,20 +184,30 @@ static void _conf(const char *name, int mode, int syslog_facility, strncpy(logt_logfile, logfile, PATH_MAX - 1);
if (logt_mode & LOG_MODE_OUTPUT_FILE && logt_logfile[0]) { - if (logt_logfile_fp) { - fclose(logt_logfile_fp); - logt_logfile_fp = NULL; - } - logt_logfile_fp = fopen(logt_logfile, "a+"); - if (logt_logfile_fp != NULL) { - fd = fileno(logt_logfile_fp); - fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); - } + /* Don't close the existing fp in this thread, let the main logthread do it later */ + if (!logt_logfile_fp) { + logt_logfile_fp = fopen(logt_logfile, "a+"); + if (logt_logfile_fp != NULL) { + fd = fileno(logt_logfile_fp); + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); + } + } + else { + new_logt_logfile_fp = fopen(logt_logfile, "a+"); + if (new_logt_logfile_fp != NULL) { + fd = fileno(new_logt_logfile_fp); + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC); + } + } } else { if (logt_logfile_fp) { fclose(logt_logfile_fp); logt_logfile_fp = NULL; } + if (new_logt_logfile_fp) { + fclose(new_logt_logfile_fp); + new_logt_logfile_fp = NULL; + } }
if (logt_mode & LOG_MODE_OUTPUT_SYSLOG) {