summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Grishenko <themiron@mail.ru>2012-09-12 17:13:55 +0600
committerWaldemar Brodkorb <wbx@openadk.org>2015-12-17 20:35:20 +0100
commit64917add7f4aeec8720d2fba5e96ea39aac35623 (patch)
tree48653a0e510b8c25c563688b90f92a63169352b7
parent8a992d6715c8149f7efc0553eeaf31f3e27de60c (diff)
Fix syslog messages lost after syslogd restarts
If syslogd is stopped and restarted while a process has the log open, the next message that process produces will be logged to the console and not to the new instance of syslogd. Further messages will be routed correctly, but not the first one. Based on original patch Bug 3889 - syslog loses messages when syslogd restarted https://bugs.busybox.net/show_bug.cgi?id=3889 function old new delta openlog 33 68 +35 __vsyslog 851 848 -3 openlog_intern 318 259 -59 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 35/-62) Total: -27 bytes Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
-rw-r--r--libc/misc/syslog/syslog.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c
index 1ab470700..72afabb83 100644
--- a/libc/misc/syslog/syslog.c
+++ b/libc/misc/syslog/syslog.c
@@ -122,23 +122,15 @@ closelog_intern(int sig)
}
static void
-openlog_intern(const char *ident, int logstat, int logfac)
+openlog_intern(void)
{
int fd;
int logType = SOCK_DGRAM;
- if (ident != NULL)
- LogTag = ident;
- LogStat = logstat;
- /* (we were checking also for logfac != 0, but it breaks
- * openlog(xx, LOG_KERN) since LOG_KERN == 0) */
- if ((logfac & ~LOG_FACMASK) == 0) /* if we don't have invalid bits */
- LogFacility = (unsigned)logfac >> 3;
-
fd = LogFile;
if (fd == -1) {
retry:
- if (logstat & LOG_NDELAY) {
+ if (1) { /* if statement left in to make .diff cleaner */
LogFile = fd = socket(AF_UNIX, logType, 0);
if (fd == -1) {
return;
@@ -172,7 +164,18 @@ void
openlog(const char *ident, int logstat, int logfac)
{
__UCLIBC_MUTEX_LOCK(mylock);
- openlog_intern(ident, logstat, logfac);
+
+ if (ident != NULL)
+ LogTag = ident;
+ LogStat = logstat;
+ /* (we were checking also for logfac != 0, but it breaks
+ * openlog(xx, LOG_KERN) since LOG_KERN == 0) */
+ if ((logfac & ~LOG_FACMASK) == 0) /* if we don't have invalid bits */
+ LogFacility = (unsigned)logfac >> 3;
+
+ if (logstat & LOG_NDELAY)
+ openlog_intern();
+
__UCLIBC_MUTEX_UNLOCK(mylock);
}
@@ -206,7 +209,7 @@ __vsyslog(int pri, const char *fmt, va_list ap)
if ((LogMask & LOG_MASK(LOG_PRI(pri))) == 0)
goto getout;
if (LogFile < 0 || !connected)
- openlog_intern(NULL, LogStat | LOG_NDELAY, (int)LogFacility << 3);
+ openlog_intern();
/* Set default facility if none specified. */
if ((pri & LOG_FACMASK) == 0)
@@ -266,14 +269,23 @@ __vsyslog(int pri, const char *fmt, va_list ap)
/* Output the message to the local logger using NUL as a message delimiter. */
p = tbuf;
*last_chr = '\0';
+ retry:
if (LogFile >= 0) {
do {
/* can't just use write, it can result in SIGPIPE */
rc = send(LogFile, p, last_chr + 1 - p, MSG_NOSIGNAL);
if (rc < 0) {
- /* I don't think looping forever on EAGAIN is a good idea.
- * Imagine that syslogd is SIGSTOPed... */
- if (/* (errno != EAGAIN) && */ (errno != EINTR)) {
+ switch (errno) {
+ case EINTR:
+ break;
+ case ECONNRESET:
+ /* syslogd restarted, reopen log */
+ closelog_intern(1);
+ openlog_intern();
+ goto retry;
+ case EAGAIN:
+ /* syslogd stalled, noting we can do */
+ default:
closelog_intern(1); /* 1: do not reset LogXXX globals to default */
goto write_err;
}