From 1414fde173e15a9bba630b25ce9c50ec7a38a223 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 12 Feb 2015 16:41:26 +0100 Subject: [PATCH] Logging: Added log_drop_stderr(). When writing the daemonization module, I assumed that it is not necessary to close stderr, because it will be replaced by a log file later. Alas, this is not true for general log streams. I have added a function, which should be called by the daemon when it is done with initialization of logging. --- maint/libucw.abi | 1 + ucw/doc/daemon.txt | 3 ++- ucw/log-file.c | 19 +++++++++++++++++-- ucw/log.h | 12 +++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/maint/libucw.abi b/maint/libucw.abi index e81ac9c0..813398f2 100644 --- a/maint/libucw.abi +++ b/maint/libucw.abi @@ -304,6 +304,7 @@ log_new_fd log_switch_disable log_switch_enable log_switch +log_drop_stderr log_new_syslog log_syslog_facility_exists log_new_configured diff --git a/ucw/doc/daemon.txt b/ucw/doc/daemon.txt index 58d550f2..f6037b60 100644 --- a/ucw/doc/daemon.txt +++ b/ucw/doc/daemon.txt @@ -14,7 +14,8 @@ helper which performs the necessary actions. Namely: set according to `/etc/passwd` and `/etc/group`. * Redirecting standard input and output from `/dev/null`. Standard error output is left open, so that error messages can be printed before you - set up proper <>. + set up proper <>. If you are not sure that your log streams + replaced stderr, you can call <> to do that. * Setting the `umask()` to a fixed value (022). * Switching from the current directory to `/`, so that it is not kept busy. * Writing a PID file. While the daemon is running, the PID file is kept locked diff --git a/ucw/log-file.c b/ucw/log-file.c index 40f1f396..40871418 100644 --- a/ucw/log-file.c +++ b/ucw/log-file.c @@ -1,7 +1,7 @@ /* * UCW Library -- Logging to Files * - * (c) 1997--2009 Martin Mares + * (c) 1997--2015 Martin Mares * (c) 2008 Tomas Gavenciak * * This software may be freely distributed and used according to the terms @@ -32,6 +32,7 @@ struct file_stream { #define MAX_EXPAND 64 // Maximum size of expansion of strftime escapes static int log_switch_nest; +static bool log_stderr_replaced; static void do_log_reopen(struct file_stream *fs, const char *name) @@ -43,7 +44,10 @@ do_log_reopen(struct file_stream *fs, const char *name) close(fs->fd); fs->fd = fd; if (fs->flags & FF_FD2_FOLLOWS) - dup2(fd, 2); + { + dup2(fd, 2); + log_stderr_replaced = 1; + } if (fs->ls.name) { xfree(fs->ls.name); @@ -181,6 +185,17 @@ log_file(const char *name) log_set_default_stream(log_new_file(name, FF_FD2_FOLLOWS)); } +void +log_drop_stderr(void) +{ + if (!log_stderr_replaced) + { + if (dup2(1, 2) < 0) + die("Cannot get rid of stderr: %m"); + log_stderr_replaced = 1; + } +} + #ifdef TEST int main(int argc, char **argv) diff --git a/ucw/log.h b/ucw/log.h index 6ff2d4e5..7724c6c0 100644 --- a/ucw/log.h +++ b/ucw/log.h @@ -1,7 +1,7 @@ /* * UCW Library -- Logging * - * (c) 1997--2009 Martin Mares + * (c) 1997--2015 Martin Mares * (c) 2008 Tomas Gavenciak * * This software may be freely distributed and used according to the terms @@ -19,6 +19,7 @@ #define log_close_all ucw_log_close_all #define log_close_stream ucw_log_close_stream #define log_configured ucw_log_configured +#define log_drop_stderr ucw_log_drop_stderr #define log_find_type ucw_log_find_type #define log_new_configured ucw_log_new_configured #define log_new_fd ucw_log_new_fd @@ -258,6 +259,15 @@ void log_switch_disable(void); void log_switch_enable(void); /** Negate the effect of log_switch_disable(). **/ int log_switch(void); /** Switch log files manually. **/ +/** + * Drop stderr if it is not already redirected to a log file. + * This is usually needed in daemons to make sure that the original + * stderr does not stay open (stdin and stdout are dropped by our + * <> automatically). More specifically, + * it makes stderr a clone of stdout. + **/ +void log_drop_stderr(void); + /*** * === Logging to syslog * -- 2.39.2