Skip to content

Commit

Permalink
Fix #29: prevent repeating kernel messages when syslogd is restarted
Browse files Browse the repository at this point in the history
This patch fixes the problem with kernel messages being repeated when
syslogd is restarted at runtime.  This is achieved by caching the last
seqno read from /dev/kmsg to /run/syslogd.cache.  The latter is usually
a ram disk these days so it should be a fairly quick op.

Excessive updates are prevented by only caching after handling all
callbacks in the socket_poll() loop, and only updating the cache
if there has been any new kernel messages since last update.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
  • Loading branch information
troglobit committed May 5, 2021
1 parent a38daf0 commit 92a4fb3
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Expand Up @@ -14,6 +14,7 @@ Bug fix release.
the bundled logger, the `syslog()` API in the C library is used, which
may not necessarily set the timestamp. When sysklogd infers timestamp
it was offset by the number of years since 1969, i.e., `boot_time`
- Issue #29: kernel messages repeated if syslogd is restarted at runtime
- Issue #31: time calculation issue on 32-bit systems
- Issue #32: remote kernel messages being mapped to uucp instead of user

Expand Down
58 changes: 58 additions & 0 deletions src/syslogd.c
Expand Up @@ -60,6 +60,7 @@ static char sccsid[] __attribute__((unused)) =
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
Expand Down Expand Up @@ -122,6 +123,7 @@ struct filed consfile;
static int Debug; /* debug flag */
static int Foreground = 0; /* don't fork - don't run in daemon mode */
static time_t boot_time; /* Offset for printsys() */
static uint64_t sys_seqno = 0; /* Last seen kernel log message */
static int resolve = 1; /* resolve hostname */
static char LocalHostName[MAXHOSTNAMELEN + 1]; /* our hostname */
static char *LocalDomain; /* our local domain name */
Expand Down Expand Up @@ -195,6 +197,54 @@ static int addpeer(struct peer *pe0)
return 0;
}

static void sys_seqno_load(void)
{
char buf[32], *str;
FILE *fp;

fp = fopen(_PATH_CACHE, "r");
if (!fp)
return;

while ((str = fgets(buf, sizeof(buf), fp))) {
uint64_t val;
char *end;

if (str[strlen(str) - 1] == '\n')
str[strlen(str) - 1] = 0;

errno = 0;
val = strtoull(str, &end, 10);
if (val == 0 && end == str)
break; /* str was not a number */
else if (val == ULLONG_MAX && errno)
break; /* the value of str does not fit in unsigned long long */
else if (*end)
break; /* str began with a number but has junk left over at the end */

sys_seqno = val;
}
fclose(fp);
}

static void sys_seqno_save(void)
{
static uint64_t prev = 0;
FILE *fp;

if (prev == sys_seqno)
return; /* no changes since last save */

fp = fopen(_PATH_CACHE, "w");
if (!fp)
return; /* best effort, ignore any errors */

fprintf(fp, "%" PRIu64 "\n", sys_seqno);
fclose(fp);

prev = sys_seqno;
}

int usage(int code)
{
printf("Usage:\n"
Expand Down Expand Up @@ -389,6 +439,7 @@ int main(int argc, char *argv[])
* /dev/kmsg and fall back to _PROC_KLOG, which on GLIBC
* systems is /proc/kmsg, and /dev/klog on *BSD.
*/
sys_seqno_load();
if (opensys("/dev/kmsg")) {
if (opensys(_PATH_KLOG))
warn("Kernel logging disabled, failed opening %s", _PATH_KLOG);
Expand Down Expand Up @@ -453,6 +504,8 @@ int main(int argc, char *argv[])

if (rc < 0 && errno != EINTR)
ERR("select()");

sys_seqno_save();
}
}

Expand Down Expand Up @@ -1134,6 +1187,11 @@ void printsys(char *msg)
while (isdigit(*p))
seqno = 10 * seqno + (*p++ - '0');

/* Check if logged already (we've been restarted) */
if (sys_seqno > 0 && seqno <= sys_seqno)
return;
sys_seqno = seqno;

p++; /* skip ',' */

/* timestamp */
Expand Down
4 changes: 4 additions & 0 deletions src/syslogd.h
Expand Up @@ -85,6 +85,10 @@
#define _PATH_LOGPID RUNSTATEDIR "/syslogd.pid"
#endif

#ifndef _PATH_CACHE
#define _PATH_CACHE RUNSTATEDIR "/syslogd.cache"
#endif

#ifndef _PATH_DEV
#define _PATH_DEV "/dev/"
#endif
Expand Down

0 comments on commit 92a4fb3

Please sign in to comment.