From 138d03db194778c92dc7ebee00c7f1c0e937233e Mon Sep 17 00:00:00 2001 From: Justin Maggard Date: Tue, 23 Jan 2018 22:01:10 -0800 Subject: [PATCH] Reload log file on SIGHUP There's a report about a nightly "crash" when users download, compile from source, and replace their distro's mindlnad binary. This is because the Debian package includes a patch that uses SIGUSR2 to reopen the log file and sends SIGUSR2 from logrotate instead of just using the "copytruncate" logrotate option. Then logrotate sends SIGUSR2 at 6:25AM, which causes us to abort due to the unhandled signal. I don't want to sacrifice SIGUSR2 just for log rotation, especially when we already do some reload operations on SIGHUP. So to avoid this Debian/Ubuntu issue, we'll explicitly ignore SIGUSR2, and add log file reopening to the SIGHUP handler. Then hopefully a future Debian package version will remove the SIGUSR2 patch and use SIGHUP instead (or copytruncate). Fixes: SF Bug #313 (log rotation kills minidlna service) --- log.c | 47 ++++++++++++++++++++++++++++++------------ log.h | 3 ++- minidlna.c | 53 +++++++++++++++++++----------------------------- upnpglobalvars.c | 4 ++-- upnpglobalvars.h | 10 +++++++-- 5 files changed, 67 insertions(+), 50 deletions(-) diff --git a/log.c b/log.c index f80e6d4..a989904 100644 --- a/log.c +++ b/log.c @@ -63,28 +63,46 @@ log_close(void) fclose(log_fp); } -int find_matching_name(const char* str, const char* names[]) { - if (str == NULL) return -1; +void +log_reopen(void) +{ + if (log_path[0] && log_fp) + { + char logfile[1048]; + snprintf(logfile, sizeof(logfile), "%s/" LOGFILE_NAME, log_path); + fclose(log_fp); + log_fp = fopen(logfile, "a"); + DPRINTF(E_INFO, L_GENERAL, "Reopened log file\n"); + } +} - const char* start = strpbrk(str, ",="); - int level, c = (start != NULL) ? start - str : strlen(str); +int find_matching_name(const char* str, const char* names[]) +{ + const char *start; + int level, c; + + if (!str) + return -1; + + start = strpbrk(str, ",="); + c = start ? start - str : strlen(str); for (level = 0; names[level] != 0; level++) { - if (!(strncasecmp(names[level], str, c))) + if (!strncasecmp(names[level], str, c)) return level; } return -1; } int -log_init(const char *fname, const char *debug) +log_init(const char *debug) { int i; - FILE *fp; + FILE *fp = NULL; int level = find_matching_name(debug, level_name); int default_log_level = (level == -1) ? _default_log_level : level; - for (i=0; ipw_name; } @@ -710,16 +710,15 @@ init(int argc, char **argv) make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); if (access(path, F_OK) != 0) DPRINTF(E_FATAL, L_GENERAL, "Database path not accessible! [%s]\n", path); - strncpyt(db_path, path, PATH_MAX); + strncpyt(db_path, path, sizeof(db_path)); break; case UPNPLOGDIR: path = realpath(ary_options[i].value, buf); if (!path) - path = (ary_options[i].value); - make_dir(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); - if (access(path, F_OK) != 0) - DPRINTF(E_FATAL, L_GENERAL, "Log path not accessible! [%s]\n", path); - strncpyt(log_path, path, PATH_MAX); + path = ary_options[i].value; + if (snprintf(log_path, sizeof(log_path), "%s", path) > sizeof(log_path)) + DPRINTF(E_FATAL, L_GENERAL, "Log path too long! [%s]\n", path); + make_dir(log_path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO); break; case UPNPLOGLEVEL: log_level = ary_options[i].value; @@ -816,15 +815,10 @@ init(int argc, char **argv) optionsfile); } } - if (log_path[0] == '\0') - { - if (db_path[0] == '\0') - strncpyt(log_path, DEFAULT_LOG_PATH, PATH_MAX); - else - strncpyt(log_path, db_path, PATH_MAX); - } - if (db_path[0] == '\0') - strncpyt(db_path, DEFAULT_DB_PATH, PATH_MAX); + if (!log_path[0]) + strncpyt(log_path, DEFAULT_LOG_PATH, sizeof(log_path)); + if (!db_path[0]) + strncpyt(db_path, DEFAULT_DB_PATH, sizeof(db_path)); /* command line arguments processing */ for (i=1; i