Gitweb:
http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=9d6a1843fef...
Commit: 9d6a1843fefe0799065afbe5d0a7637fed6887fc
Parent: 2f05327bd8e7a072418dca45988ab5a814109258
Author: Christine Caulfield <ccaulfie(a)redhat.com>
AuthorDate: Thu Oct 30 09:43:35 2014 +0000
Committer: Christine Caulfield <ccaulfie(a)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(a)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) {