[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