[patches] [say 1/2] say: Wrap logrotate signal handler with ev_signal

Georgy Kirichenko georgy at tarantool.org
Fri Feb 16 10:40:34 MSK 2018


This seems as a good patch but there is one more issue:
coio_task_post does an yield, but we don't want it on tasks posting, because 
logs list may be changed while we are in a curent task waiting.
I think the better way is to modify coio_task_post to not to do any yield if 
timeout is zero and use it while log rotate tasks posting.
@Kostya, please get a feedback

On Thursday, February 15, 2018 6:10:01 PM MSK imarkov wrote:
> 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..9d2a174 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, TIMEOUT_INFINITY) != 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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.tarantool.org/pipermail/tarantool-patches/attachments/20180216/092f8b86/attachment.sig>


More information about the Tarantool-patches mailing list