Replaced log locking using mutex with fcntl lock

When reloading Nginx, there is a race condition which is visible under high
load. As the logging mutex is shared between multiple workers, when a worker
is sent a stop signal during a reload, and the log mutex is held, write()
will never return, which means that the mutex will never unlock. As other
workers share this mutex, they will deadlock.

fcntl does not suffer from this issue.
This commit is contained in:
Fred Nicolson 2018-11-07 15:57:33 +00:00 committed by Felipe Zimmerle
parent 5a4ada39bc
commit 3d2030426c
No known key found for this signature in database
GPG Key ID: E6DFB08CE8B11277
2 changed files with 11 additions and 6 deletions

View File

@ -104,7 +104,6 @@ std::pair<msc_file_handler *, FILE *> SharedFiles::add_new_handler(
if (toBeCreated) {
memset(new_debug_log, '\0', sizeof(msc_file_handler_t));
pthread_mutex_init(&new_debug_log->lock, NULL);
new_debug_log->shm_id_structure = shm_id;
memcpy(new_debug_log->file_name, fileName.c_str(), fileName.size());
new_debug_log->file_name[fileName.size()] = '\0';
@ -222,6 +221,7 @@ bool SharedFiles::write(const std::string& fileName,
std::pair<msc_file_handler *, FILE *> a;
std::string lmsg = msg;
size_t wrote;
struct flock lock{};
bool ret = true;
a = find_handler(fileName);
@ -230,15 +230,21 @@ bool SharedFiles::write(const std::string& fileName,
return false;
}
pthread_mutex_lock(&a.first->lock);
wrote = fwrite(reinterpret_cast<const char *>(lmsg.c_str()), 1,
lmsg.size(), a.second);
//Exclusively lock whole file
lock.l_start = lock.l_len = lock.l_whence = 0;
lock.l_type = F_WRLCK;
fcntl(fileno(a.second), F_SETLKW, &lock);
wrote = fwrite(lmsg.c_str(), 1, lmsg.size(), a.second);
if (wrote < msg.size()) {
error->assign("failed to write: " + fileName);
ret = false;
}
fflush(a.second);
pthread_mutex_unlock(&a.first->lock);
//Remove exclusive lock
lock.l_type = F_UNLCK;
fcntl(fileno(a.second), F_SETLKW, &lock);
return ret;
}

View File

@ -50,7 +50,6 @@ namespace utils {
typedef struct msc_file_handler {
int shm_id_structure;
pthread_mutex_t lock;
char file_name[];
} msc_file_handler_t;