[patches] [say 2/3] say: Wrap logrotate signal handler with ev_signal
imarkov
imarkov at tarantool.org
Tue Feb 20 18:28:28 MSK 2018
From: IlyaMarkovMipt <markovilya197 at gmail.com>
Current log rotation is not async signal safe.
In order to make it so refactor signal handling
with ev_signal.
Log rotation for each logger performs in separate
coio_task to provide async and thread-safe execution.
Relates #3015
---
src/lua/log.lua | 8 ++++++--
src/main.cc | 3 ++-
src/say.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++----------
src/say.h | 5 ++++-
4 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/src/lua/log.lua b/src/lua/log.lua
index b90eb88..0ac0e8f 100644
--- a/src/lua/log.lua
+++ b/src/lua/log.lua
@@ -12,7 +12,11 @@ ffi.cdef[[
extern sayfunc_t _say;
- extern void say_logrotate(int);
+ extern struct ev_loop;
+ extern struct ev_signal;
+
+ extern void
+ say_logrotate(struct ev_loop *, struct ev_signal *, int);
enum say_level {
S_FATAL,
@@ -104,7 +108,7 @@ local function say_closure(lvl)
end
local function log_rotate()
- ffi.C.say_logrotate(0)
+ ffi.C.say_logrotate(nil, nil, 0)
end
local function log_level(level)
diff --git a/src/main.cc b/src/main.cc
index ec06103..1682bae 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -83,7 +83,7 @@ static char *pid_file = NULL;
static char **main_argv;
static int main_argc;
/** Signals handled after start as part of the event loop. */
-static ev_signal ev_sigs[5];
+static ev_signal ev_sigs[6];
static const int ev_sig_count = sizeof(ev_sigs)/sizeof(*ev_sigs);
static double start_time;
@@ -335,6 +335,7 @@ signal_init(void)
ev_signal_init(&ev_sigs[2], signal_cb, SIGTERM);
ev_signal_init(&ev_sigs[3], signal_cb, SIGHUP);
ev_signal_init(&ev_sigs[4], signal_sigwinch_cb, SIGWINCH);
+ ev_signal_init(&ev_sigs[5], say_logrotate, SIGHUP);
for (int i = 0; i < ev_sig_count; i++)
ev_signal_start(loop(), &ev_sigs[i]);
diff --git a/src/say.c b/src/say.c
index 65808a6..34ada7a 100644
--- a/src/say.c
+++ b/src/say.c
@@ -42,6 +42,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
+#include <coio_task.h>
pid_t log_pid = 0;
int log_level = S_INFO;
@@ -265,26 +266,66 @@ log_rotate(const struct log *log)
ssize_t r = write(log->fd,
logrotate_message, (sizeof logrotate_message) - 1);
(void) r;
+ /*
+ * log_background applies only to log_default logger
+ */
+ if (log == log_default && log_background &&
+ log->type == SAY_LOGGER_FILE) {
+ dup2(log_default->fd, STDOUT_FILENO);
+ dup2(log_default->fd, STDERR_FILENO);
+ }
+
+ return 0;
+}
+
+struct rotate_task {
+ struct coio_task base;
+ struct log *log;
+};
+
+static int
+logrotate_cb(struct coio_task *ptr)
+{
+ struct rotate_task *task = (struct rotate_task *) ptr;
+ if (log_rotate(task->log) < 0) {
+ diag_log();
+ }
+ return 0;
+}
+
+static int
+logrotate_cleanup_cb(struct coio_task *ptr)
+{
+ struct rotate_task *task = (struct rotate_task *) ptr;
+ coio_task_destroy(&task->base);
+ free(task);
return 0;
}
void
-say_logrotate(int signo)
+say_logrotate(struct ev_loop *loop, struct ev_signal *w, int revents)
{
- (void) signo;
+ (void) loop;
+ (void) w;
+ (void) revents;
int saved_errno = errno;
struct log *log;
rlist_foreach_entry(log, &log_rotate_list, in_log_list) {
- if (log_rotate(log) < 0) {
+ struct rotate_task *task =
+ (struct rotate_task *) calloc(1, sizeof(*task));
+ if (task == NULL) {
+ diag_set(OutOfMemory, sizeof(*task), "malloc",
+ "say_logrotate");
diag_log();
+ continue;
}
- }
- /*
- * log_background applies only to log_default logger
- */
- if (log_background && log_default->type == SAY_LOGGER_FILE) {
- dup2(log_default->fd, STDOUT_FILENO);
- dup2(log_default->fd, STDERR_FILENO);
+ coio_task_create(&task->base, logrotate_cb, logrotate_cleanup_cb);
+ task->log = log;
+ if (coio_task_post(&task->base, 0) != 0) {
+ say_error("log_rotate: failed to post a task");
+ continue;
+ }
+ logrotate_cleanup_cb(&task->base);
}
errno = saved_errno;
}
@@ -535,7 +576,6 @@ say_logger_init(const char *init_str, int level, int nonblock,
say_set_log_level(level);
log_background = background;
log_pid = log_default->pid;
- signal(SIGHUP, say_logrotate);
say_set_log_format(say_format_by_name(format));
if (background) {
diff --git a/src/say.h b/src/say.h
index 1b63229..46e6976 100644
--- a/src/say.h
+++ b/src/say.h
@@ -185,8 +185,11 @@ say_set_log_format(enum say_format format);
enum say_format
say_format_by_name(const char *format);
+struct ev_loop;
+struct ev_signal;
+
void
-say_logrotate(int /* signo */);
+say_logrotate(struct ev_loop *, struct ev_signal *, int /* revents */);
/** Init default logger. */
void
--
2.7.4
More information about the Tarantool-patches
mailing list