summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac2
-rw-r--r--doc/imjournal.html86
-rw-r--r--doc/imrelp.html6
-rw-r--r--doc/manual.html2
-rw-r--r--doc/omfile.html8
-rw-r--r--doc/omjournal.html3
-rwxr-xr-xplugins/imjournal/imjournal.c116
-rw-r--r--plugins/imzmq3/imzmq3.c70
-rw-r--r--rsyslog.service.in3
-rw-r--r--runtime/ratelimit.c26
-rw-r--r--runtime/ratelimit.h2
-rw-r--r--tools/syslogd.c2
14 files changed, 296 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f8d7cc..8250a92 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,23 @@
---------------------------------------------------------------------------
+Version 7.4.1 [v7.4-stable] 2013-06-17
+- imjournal: add ratelimiting capability
+ The original imjournal code did not support ratelimiting at all. We
+ now have our own ratelimiter. This can mitigate against journal
+ database corruption, when the journal re-sends old data. This is a
+ current bug in systemd journal, but we won't outrule this to happen
+ in the future again. So it is better to have a safeguard in place.
+ By default, we permit 20,000 messages witin 10 minutes. This may
+ be a bit restrictive, but given the risk potential it seems reasonable.
+ Users requiring larger traffic flows can always adjust the value.
+- bugfix: potential loop in rate limiting
+ if the message that tells about rate-limiting gets rate-limited itself,
+ it will potentially create and endless loop
+- bugfix: potential segfault in imjournal if journal DB is corrupted
+- bugfix: prevent a segfault in imjournal if state file is not defined
+- bugfix imzmq3: potential segfault on startup
+ if no problem happend at startup, everything went fine
+ Thanks to Hongfei Cheng and Brian Knox for the patch
+---------------------------------------------------------------------------
Version 7.4.0 [v7.4-stable] 2013-06-06
This starts a new stable branch based on 7.3.15 plus the following changes:
- add --enable-cached-man-pages ./configure option
diff --git a/configure b/configure
index 53907ea..4f78940 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for rsyslog 7.4.0.
+# Generated by GNU Autoconf 2.69 for rsyslog 7.4.1.
#
# Report bugs to <rsyslog@lists.adiscon.com>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='rsyslog'
PACKAGE_TARNAME='rsyslog'
-PACKAGE_VERSION='7.4.0'
-PACKAGE_STRING='rsyslog 7.4.0'
+PACKAGE_VERSION='7.4.1'
+PACKAGE_STRING='rsyslog 7.4.1'
PACKAGE_BUGREPORT='rsyslog@lists.adiscon.com'
PACKAGE_URL=''
@@ -1612,7 +1612,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures rsyslog 7.4.0 to adapt to many kinds of systems.
+\`configure' configures rsyslog 7.4.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1682,7 +1682,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of rsyslog 7.4.0:";;
+ short | recursive ) echo "Configuration of rsyslog 7.4.1:";;
esac
cat <<\_ACEOF
@@ -1929,7 +1929,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-rsyslog configure 7.4.0
+rsyslog configure 7.4.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2509,7 +2509,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by rsyslog $as_me 7.4.0, which was
+It was created by rsyslog $as_me 7.4.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3333,7 +3333,7 @@ fi
# Define the identity of the package.
PACKAGE='rsyslog'
- VERSION='7.4.0'
+ VERSION='7.4.1'
cat >>confdefs.h <<_ACEOF
@@ -20624,7 +20624,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by rsyslog $as_me 7.4.0, which was
+This file was extended by rsyslog $as_me 7.4.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -20690,7 +20690,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-rsyslog config.status 7.4.0
+rsyslog config.status 7.4.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index ce24f53..bb0de0c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[7.4.0],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[7.4.1],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
diff --git a/doc/imjournal.html b/doc/imjournal.html
index e3f6450..28b4701 100644
--- a/doc/imjournal.html
+++ b/doc/imjournal.html
@@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
-<meta http-equiv="Content-Language" content="en"><title>Text File Input Monitor</title></head>
+<meta http-equiv="Content-Language" content="en"><title>Systemd Journal Input Module</title></head>
<body>
<a href="rsyslog_conf_modules.html">back</a>
@@ -11,35 +11,101 @@
<p><b>Description</b>:</p>
<p>Provides the ability to import structured log messages from systemd journal
to syslog.</p>
+<p>Note that this module reads the journal database, what is considered a
+relativly performance-intense operation. As such, the performance of a
+configuration utilizing this
+module may be notably slower then when using
+<a href="imuxsock.html">imuxsock</a>. The journal provides imuxsock with a
+copy of all "classical" syslog messages, however, it does not provide
+structured data. If the latter is needed, imjournal must be used. Otherwise,
+imjournal may be simply replaced by imuxsock.
+<p>We suggest to check out our short presentation on
+<a href="http://youtu.be/GTS7EuSdFKE">rsyslog journal integration</a> to
+learn more details of anticipated use cases.
+
+<p><b>Warning:</b> Some versions of systemd journal have problems with database
+corruption, which leads to the journal to return the same data endlessly
+in a thight loop. This results in massive message duplication inside rsyslog
+probably resulting in a denial-of-service when the system ressouces get
+exhausted. This can be somewhat mitigated by using proper rate-limiters, but
+even then there are spikes of old data which are endlessly repeated. By default,
+ratelimiting is activated and permits to process 20,000 messages within 10
+seconds, what should be well enough for most use cases. If insufficient, use
+the parameters described below to adjust the permitted volume.
+<b>It is strongly recommended to use this plugin only if there
+is hard need to do so.</b>
<p><b>Configuration Directives</b>:</p>
<p><b>Module Directives</b></p>
<ul>
-<li><span style="font-weight: bold;">PersistStateInterval
-messages</span><br>
+<li><b>PersistStateInterval</b> number-of-messages<br>
This is a global setting. It specifies how often should the journal state be persisted.
+The persists happens after each <i>number-of-messages</i>.
This option is useful for rsyslog to start reding from the last journal message it read.
-<li><span style="font-weight: bold;">StateFile
-/path/to/file</span><br>
+<li><b>StateFile</b> /path/to/file<br>
This is a global setting. It specifies where the state file for persisting
journal state is located.
+
+<li><b>ratelimit.interval</b> seconds (default: 600)<br>
+Specifies the interval in seconds onto which rate-limiting is to be applied.
+If more than ratelimit.burst messages are read during that interval, further
+messages up to the end of the interval are discarded. The number of messages
+discarded is emitted at the end of the interval (if there were any discards).
+<br>Setting this to value zero turns off ratelimiting. Note that it is
+<b>not recommended to turn of ratelimiting</b>, except that you know for
+sure journal database entries will never be corrupted. Without ratelimiting,
+a corrupted systemd journal database may cause a kind of denial of service (we
+are stressing this point as multiple users have reported us such problems
+with the journal database - information current as of June 2013).
+
+<li><b>ratelimit.burst</b> messages (default: 20000)<br>
+Specifies the maximum number of messages that can be emitted within the
+ratelimit.interval interval. For futher information, see description there.
+
+<li><b>IgnorePreviousMessages</b> [<b>off</b>/on]<br>
+This option specifies whether imjournal should ignore messages currently in
+journal and read only new messages. This option is only used when there is
+no StateFile to avoid message loss.
</ul>
+
<b>Caveats/Known Bugs:</b>
<p>
+<ul>
+<li>As stated above, a corrupted systemd journal database can cause major
+problems, depending on what the corruption results in. This is beyond the
+control of the rsyslog team.
+</ul>
</p>
<p><b>Sample:</b></p>
<p>
-The following example shows pulling structured imjournal messages and saving them into /var/log/ceelog
+The following example shows pulling structured imjournal messages and saving them into /var/log/ceelog.
</p>
-<textarea rows="15" cols="60">
+<textarea rows="11" cols="80">
module(load="imjournal" PersistStateInterval="100" StateFile="/path/to/file") #load imjournal module
module(load="mmjsonparse") #load mmjsonparse module for structured logs
-$template CEETemplate,"%TIMESTAMP% %HOSTNAME% %syslogtag% @cee: %$!all-json%\n" #template for messages
+template(name="CEETemplate" type="string"
+ string="%TIMESTAMP% %HOSTNAME% %syslogtag% @cee: %$!all-json%\n"
+ ) #template for messages
-*.* :mmjsonparse:
-*.* /var/log/ceelog;CEETemplate
+action(type="mmjsonparse")
+action(type="omfile" file="/var/log/ceelog" template="CEETemplate")
</textarea>
+
+<p><b>Legacy Configuration Directives</b>:</p>
+<ul>
+<li><b>$imjournalPersistStateInterval</b><br>
+Equivalent to: PersistStateInterval</li>
+<li><b>$imjournalStateFile</b><br>
+Equivalent to: StateFile</li>
+<li><b>$imjournalRatelimitInterval</b><br>
+Equivalent to: ratelimit.interval</li>
+<li><b>$imjournalRatelimitBurst</b><br>
+Equivalent to: ratelimit.burst</li>
+<li><strong>$ImjournalIgnorePreviousMessages</strong><br>
+Equivalent to: ignorePreviousMessages</li>
+</ul>
+
</body>
</html>
diff --git a/doc/imrelp.html b/doc/imrelp.html
index 9f3e487..f7fcc4b 100644
--- a/doc/imrelp.html
+++ b/doc/imrelp.html
@@ -30,14 +30,12 @@ Clients send messages to the RELP server via omrelp.</p>
<p><b>Configuration Directives</b>:</p>
<ul>
-<li><b>Ruleset</b> &lt;name&gt;</br>
-Binds the specified ruleset to all RELP listeners.
<li><b>Port</b> &lt;port&gt;<br>
Starts a RELP server on selected port</li>
</ul>
<b>Caveats/Known Bugs:</b>
<ul>
-<li>see description</li>
+<li>ruleset can only be bound via legacy configuration format</li>
<li>To obtain the remote system's IP address, you need to have at least
librelp 1.0.0 installed. Versions below it return the hostname instead
of the IP address.</li>
@@ -54,7 +52,7 @@ input(type="imrelp" port="20514")
<p><b>Legacy Configuration Directives</b>:</p>
<ul>
<li>InputRELPServerBindRuleset &lt;name&gt; (available in 6.3.6+)</br>
-equivalent to: RuleSet
+Binds the specified ruleset to all RELP listeners.
<li>InputRELPServerRun &lt;port&gt;<br>
equivalent to: Port</li>
</ul>
diff --git a/doc/manual.html b/doc/manual.html
index dea0b82..bc57c13 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ professional services</a> available directly from the source!</p>
<p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a>
to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the
project goals.</p>
-<p><b>This documentation is for version 7.4.0 (v7.4-stable branch) of rsyslog.</b>
+<p><b>This documentation is for version 7.4.1 (v7.4-stable branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/status">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/omfile.html b/doc/omfile.html
index a5c3bb3..438d694 100644
--- a/doc/omfile.html
+++ b/doc/omfile.html
@@ -111,8 +111,12 @@ File="/var/log/messages")
<p><b>Legacy Configuration Directives</b>:</p>
<ul>
- <li><strong>$DynaFileCacheSize </strong>(not mandatory, default will be used)<br>
- Defines a template to be used for the output. <br></li><br>
+ <li><strong>$DynaFileCacheSize </strong>(not mandatory, default 10)<br>
+ defines the maximum size of the dynafile cache for <b>this</b>
+ action. Cache size greatly affects performance and should be
+ set so that it matches the actual need. Note that files
+ inside the cache are kept open until either rsyslogd
+ is HUPed or the file is evicted from the cache.<br></li><br>
<li><strong>$OMFileZipLevel </strong>0..9 [default 0]<br>
if greater 0, turns on gzip compression of the output file. The higher the number, the better the compression, but also the more CPU is required for zipping.<br></li><br>
diff --git a/doc/omjournal.html b/doc/omjournal.html
index c42d984..6124e40 100644
--- a/doc/omjournal.html
+++ b/doc/omjournal.html
@@ -19,6 +19,9 @@ and processed by its tools.
<p>A typical use case we had on our mind is a SOHO environment, where the
user wants to include syslog data obtained from the local router to be
part of the journal data.
+<p>We suggest to check out our short presentation on
+<a href="http://youtu.be/GTS7EuSdFKE">rsyslog journal integration</a> to
+learn more details of anticipated use cases.
<p>&nbsp;</p>
<p><b>Module Configuration Parameters</b>:</p>
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
index ae29154..36c7e04 100755
--- a/plugins/imjournal/imjournal.c
+++ b/plugins/imjournal/imjournal.c
@@ -3,7 +3,7 @@
* To test under Linux:
* emmit log message into systemd journal
*
- * Copyright (C) 2008-2012 Adiscon GmbH
+ * Copyright (C) 2008-2013 Adiscon GmbH
*
* This file is part of rsyslog.
*
@@ -33,6 +33,7 @@
#include <sys/poll.h>
#include <sys/socket.h>
#include <errno.h>
+#include <systemd/sd-journal.h>
#include "dirty.h"
#include "cfsysline.h"
@@ -47,7 +48,7 @@
#include "errmsg.h"
#include "srUtils.h"
#include "unicode-helper.h"
-#include <systemd/sd-journal.h>
+#include "ratelimit.h"
MODULE_TYPE_INPUT
MODULE_TYPE_NOKEEP
@@ -64,12 +65,18 @@ DEFobjCurrIf(errmsg)
static struct configSettings_s {
char *stateFile;
int iPersistStateInterval;
+ int ratelimitInterval;
+ int ratelimitBurst;
+ int bIgnorePrevious;
} cs;
-/* module-gloval parameters */
+/* module-global parameters */
static struct cnfparamdescr modpdescr[] = {
{ "statefile", eCmdHdlrGetWord, 0 },
- { "persiststateinterval", eCmdHdlrInt, 0 }
+ { "ratelimit.interval", eCmdHdlrInt, 0 },
+ { "ratelimit.burst", eCmdHdlrInt, 0 },
+ { "persiststateinterval", eCmdHdlrInt, 0 },
+ { "ignorepreviousmessages", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk modpblk =
{ CNFPARAMBLK_VERSION,
@@ -79,11 +86,12 @@ static struct cnfparamblk modpblk =
#define DFLT_persiststateinterval 10
-static int bLegacyCnfModGlobalsPermitted = 0;/* are legacy module-global config parameters permitted? */
+static int bLegacyCnfModGlobalsPermitted = 1;/* are legacy module-global config parameters permitted? */
static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */
static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */
+static ratelimit_t *ratelimiter = NULL;
static sd_journal *j;
/* enqueue the the journal message into the message queue.
@@ -121,7 +129,7 @@ enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *
msgAddJSON(pMsg, (uchar*)"!", json);
}
- CHKiRet(submitMsg2(pMsg));
+ CHKiRet(ratelimitAddMsg(ratelimiter, NULL, pMsg));
finalize_it:
RETiRet;
@@ -244,7 +252,13 @@ readjournal() {
SD_JOURNAL_FOREACH_DATA(j, get, l) {
/* locate equal sign, this is always present */
equal_sign = memchr(get, '=', l);
- assert (equal_sign != NULL);
+
+ /* ... but we know better than to trust the specs */
+ if (equal_sign == NULL) {
+ errmsg.LogError(0, RS_RET_ERR, "SD_JOURNAL_FOREACH_DATA()"
+ "returned a malformed field (has no '='): '%s'", get);
+ continue; /* skip the entry */
+ }
/* get length of journal data prefix */
prefixlen = ((char *)equal_sign - (char *)get);
@@ -427,12 +441,13 @@ finalize_it:
}
-BEGINrunInput
-CODESTARTrunInput
- /* this is an endless loop - it is terminated when the thread is
- * signalled to do so. This, however, is handled by the framework,
- * right into the sleep below.
- */
+/* This function loads a journal cursor from the state file.
+ */
+static rsRetVal
+loadJournalState()
+{
+ DEFiRet;
+
if (cs.stateFile[0] != '/') {
char *new_stateFile;
@@ -470,8 +485,48 @@ CODESTARTrunInput
errmsg.LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: "
"open on state file `%s' failed\n", cs.stateFile);
}
+ } else {
+ /* when IgnorePrevious, seek to the end of journal */
+ if (cs.bIgnorePrevious) {
+ if (sd_journal_seek_tail(j) < 0) {
+ char errStr[256];
+
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ errmsg.LogError(0, RS_RET_ERR,
+ "sd_journal_seek_tail() failed: '%s'", errStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+ if (sd_journal_previous(j) < 0) {
+ char errStr[256];
+
+ rs_strerror_r(errno, errStr, sizeof(errStr));
+ errmsg.LogError(0, RS_RET_ERR,
+ "sd_journal_previous() failed: '%s'", errStr);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ }
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+BEGINrunInput
+CODESTARTrunInput
+ CHKiRet(ratelimitNew(&ratelimiter, "imjournal", NULL));
+ dbgprintf("imjournal: ratelimiting burst %d, interval %d\n", cs.ratelimitBurst,
+ cs.ratelimitInterval);
+ ratelimitSetLinuxLike(ratelimiter, cs.ratelimitInterval, cs.ratelimitBurst);
+ ratelimitSetNoTimeCache(ratelimiter);
+
+ if (cs.stateFile) {
+ CHKiRet(loadJournalState());
}
+ /* this is an endless loop - it is terminated when the thread is
+ * signalled to do so. This, however, is handled by the framework.
+ */
while (glbl.GetGlobalInputTermState() == 0) {
int count = 0, r;
@@ -492,11 +547,13 @@ CODESTARTrunInput
}
CHKiRet(readjournal());
- /* TODO: This could use some finer metric. */
- count++;
- if (count == cs.iPersistStateInterval) {
- count = 0;
- persistJournalState();
+ if (cs.stateFile) { /* can't persist without a state file */
+ /* TODO: This could use some finer metric. */
+ count++;
+ if (count == cs.iPersistStateInterval) {
+ count = 0;
+ persistJournalState();
+ }
}
}
@@ -510,6 +567,8 @@ CODESTARTbeginCnfLoad
cs.iPersistStateInterval = DFLT_persiststateinterval;
cs.stateFile = NULL;
+ cs.ratelimitBurst = 20000;
+ cs.ratelimitInterval = 600;
ENDbeginCnfLoad
@@ -545,8 +604,11 @@ ENDwillRun
/* close journal */
BEGINafterRun
CODESTARTafterRun
- persistJournalState();
+ if (cs.stateFile) { /* can't persist without a state file */
+ persistJournalState();
+ }
sd_journal_close(j);
+ ratelimitDestruct(ratelimiter);
ENDafterRun
@@ -589,6 +651,12 @@ CODESTARTsetModCnf
cs.iPersistStateInterval = (int) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "statefile")) {
cs.stateFile = (char *)es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(modpblk.descr[i].name, "ratelimit.burst")) {
+ cs.ratelimitBurst = (int) pvals[i].val.d.n;
+ } else if(!strcmp(modpblk.descr[i].name, "ratelimit.interval")) {
+ cs.ratelimitInterval = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "ignorepreviousmessages")) {
+ cs.bIgnorePrevious = (int) pvals[i].val.d.n;
} else {
dbgprintf("imjournal: program error, non-handled "
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
@@ -632,10 +700,16 @@ CODEmodInit_QueryRegCFSLineHdlr
CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imjournal"), sizeof("imjournal") - 1));
CHKiRet(prop.CreateStringProp(&pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"persiststateinterval", 0, eCmdHdlrInt,
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalpersiststateinterval", 0, eCmdHdlrInt,
NULL, &cs.iPersistStateInterval, STD_LOADABLE_MODULE_ID));
- CHKiRet(omsdRegCFSLineHdlr((uchar *)"statefile", 0, eCmdHdlrGetWord,
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalratelimitinterval", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitInterval, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalratelimitburst", 0, eCmdHdlrInt,
+ NULL, &cs.ratelimitBurst, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalstatefile", 0, eCmdHdlrGetWord,
NULL, &cs.stateFile, STD_LOADABLE_MODULE_ID));
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"imjournalignorepreviousmessages", 0, eCmdHdlrBinary,
+ NULL, &cs.bIgnorePrevious, STD_LOADABLE_MODULE_ID));
ENDmodInit
diff --git a/plugins/imzmq3/imzmq3.c b/plugins/imzmq3/imzmq3.c
index 52ca5eb..08b1dbe 100644
--- a/plugins/imzmq3/imzmq3.c
+++ b/plugins/imzmq3/imzmq3.c
@@ -135,7 +135,6 @@ struct lstn_s {
/* ----------------------------------------------------------------------------
* Static definitions/initializations.
*/
-static modConfData_t* loadModConf = NULL;
static modConfData_t* runModConf = NULL;
static struct lstn_s* lcnfRoot = NULL;
static struct lstn_s* lcnfLast = NULL;
@@ -268,7 +267,7 @@ static void setDefaults(instanceConf_t* info) {
info->reconnectIVLMax = -1;
info->ipv4Only = -1;
info->affinity = -1;
-
+ info->next = NULL;
};
/* given a comma separated list of subscriptions, create a char* array of them
@@ -442,11 +441,11 @@ static rsRetVal createInstance(instanceConf_t** pinst) {
setDefaults(inst);
/* add this to the config */
- if(loadModConf->tail == NULL) {
- loadModConf->tail = loadModConf->root = inst;
+ if (runModConf->root == NULL || runModConf->tail == NULL) {
+ runModConf->tail = runModConf->root = inst;
} else {
- loadModConf->tail->next = inst;
- loadModConf->tail = inst;
+ runModConf->tail->next = inst;
+ runModConf->tail = inst;
}
*pinst = inst;
finalize_it:
@@ -696,10 +695,14 @@ ENDisCompatibleWithFeature
BEGINbeginCnfLoad
CODESTARTbeginCnfLoad
- loadModConf = pModConf;
- pModConf->pConf = pConf;
+ /* After endCnfLoad() (BEGINendCnfLoad...ENDendCnfLoad) is called,
+ * the pModConf pointer must not be used to change the in-memory
+ * config object. It's safe to use the same pointer for accessing
+ * the config object until freeCnf() (BEGINfreeCnf...ENDfreeCnf). */
+ runModConf = pModConf;
+ runModConf->pConf = pConf;
/* init module config */
- loadModConf->io_threads = 0; /* 0 means don't set it */
+ runModConf->io_threads = 0; /* 0 means don't set it */
ENDbeginCnfLoad
@@ -718,7 +721,7 @@ CODESTARTsetModCnf
if (!pvals[i].bUsed)
continue;
if (!strcmp(modpblk.descr[i].name, "ioThreads")) {
- loadModConf->io_threads = (int)pvals[i].val.d.n;
+ runModConf->io_threads = (int)pvals[i].val.d.n;
} else {
errmsg.LogError(0, RS_RET_INVALID_PARAMS,
"imzmq3: config error, unknown "
@@ -735,7 +738,14 @@ ENDsetModCnf
BEGINendCnfLoad
CODESTARTendCnfLoad
- loadModConf = NULL; /* done loading, so it becomes NULL */
+ /* Last chance to make changes to the in-memory config object for this
+ * input module. After this call, the config object must no longer be
+ * changed. */
+ if (pModConf != runModConf) {
+ errmsg.LogError(0, NO_ERRCODE, "imzmq3: pointer of in-memory config object has "
+ "changed - pModConf=%p, runModConf=%p", pModConf, runModConf);
+ }
+ assert(pModConf == runModConf);
ENDendCnfLoad
@@ -764,7 +774,12 @@ ENDcheckCnf
BEGINactivateCnfPrePrivDrop
CODESTARTactivateCnfPrePrivDrop
- runModConf = pModConf;
+ if (pModConf != runModConf) {
+ errmsg.LogError(0, NO_ERRCODE, "imzmq3: pointer of in-memory config object has "
+ "changed - pModConf=%p, runModConf=%p", pModConf, runModConf);
+ }
+ assert(pModConf == runModConf);
+
/* first create the context */
createContext();
@@ -775,12 +790,41 @@ ENDactivateCnfPrePrivDrop
BEGINactivateCnf
CODESTARTactivateCnf
+ if (pModConf != runModConf) {
+ errmsg.LogError(0, NO_ERRCODE, "imzmq3: pointer of in-memory config object has "
+ "changed - pModConf=%p, runModConf=%p", pModConf, runModConf);
+ }
+ assert(pModConf == runModConf);
ENDactivateCnf
-/*TODO: Fill this in! */
BEGINfreeCnf
+ struct lstn_s *lstn, *lstn_r;
+ instanceConf_t *inst, *inst_r;
+ sublist *sub, *sub_r;
CODESTARTfreeCnf
+ DBGPRINTF("imzmq3: BEGINfreeCnf ...\n");
+ if (pModConf != runModConf) {
+ errmsg.LogError(0, NO_ERRCODE, "imzmq3: pointer of in-memory config object has "
+ "changed - pModConf=%p, runModConf=%p", pModConf, runModConf);
+ }
+ for (lstn = lcnfRoot; lstn != NULL; ) {
+ lstn_r = lstn;
+ lstn = lstn_r->next;
+ free(lstn_r);
+ }
+ for (inst = pModConf->root ; inst != NULL ; ) {
+ for (sub = inst->subscriptions; sub != NULL; ) {
+ free(sub->subscribe);
+ sub_r = sub;
+ sub = sub_r->next;
+ free(sub_r);
+ }
+ free(inst->pszBindRuleset);
+ inst_r = inst;
+ inst = inst->next;
+ free(inst_r);
+ }
ENDfreeCnf
diff --git a/rsyslog.service.in b/rsyslog.service.in
index 08a4870..8e2d64c 100644
--- a/rsyslog.service.in
+++ b/rsyslog.service.in
@@ -1,9 +1,10 @@
[Unit]
Description=System Logging Service
+Requires=syslog.socket
[Service]
+Type=notify
ExecStart=@sbindir@/rsyslogd -n
-Sockets=syslog.socket
StandardOutput=null
[Install]
diff --git a/runtime/ratelimit.c b/runtime/ratelimit.c
index d83da2d..a808e04 100644
--- a/runtime/ratelimit.c
+++ b/runtime/ratelimit.c
@@ -128,8 +128,8 @@ tellLostCnt(ratelimit_t *ratelimit)
snprintf((char*)msgbuf, sizeof(msgbuf),
"%s: %u messages lost due to rate-limiting",
ratelimit->name, ratelimit->missed);
- logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG|LOG_INFO, msgbuf, 0);
ratelimit->missed = 0;
+ logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG|LOG_INFO, msgbuf, 0);
}
}
@@ -150,16 +150,25 @@ withinRatelimit(ratelimit_t *ratelimit, time_t tt)
goto finalize_it;
}
+ /* we primarily need "NoTimeCache" mode for imjournal, as it
+ * sets the message generation time to the journal timestamp.
+ * As such, we do not get a proper indication of the actual
+ * message rate. To prevent this, we need to query local
+ * system time ourselvs.
+ */
+ if(ratelimit->bNoTimeCache)
+ tt = time(NULL);
+
assert(ratelimit->burst != 0);
if(ratelimit->begin == 0)
ratelimit->begin = tt;
- /* resume if we go out of out time window */
+ /* resume if we go out of time window */
if(tt > ratelimit->begin + ratelimit->interval) {
- tellLostCnt(ratelimit);
ratelimit->begin = 0;
ratelimit->done = 0;
+ tellLostCnt(ratelimit);
}
/* do actual limit check */
@@ -167,13 +176,13 @@ withinRatelimit(ratelimit_t *ratelimit, time_t tt)
ratelimit->done++;
ret = 1;
} else {
- if(ratelimit->missed == 0) {
+ ratelimit->missed++;
+ if(ratelimit->missed == 1) {
snprintf((char*)msgbuf, sizeof(msgbuf),
"%s: begin to drop messages due to rate-limiting",
ratelimit->name);
logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG|LOG_INFO, msgbuf, 0);
}
- ratelimit->missed++;
ret = 0;
}
@@ -318,6 +327,12 @@ ratelimitSetThreadSafe(ratelimit_t *ratelimit)
ratelimit->bThreadSafe = 1;
pthread_mutex_init(&ratelimit->mut, NULL);
}
+void
+ratelimitSetNoTimeCache(ratelimit_t *ratelimit)
+{
+ ratelimit->bNoTimeCache = 1;
+ pthread_mutex_init(&ratelimit->mut, NULL);
+}
/* Severity level determines which messages are subject to
* ratelimiting. Default (no value set) is all messages.
@@ -368,4 +383,3 @@ ratelimitModInit(void)
finalize_it:
RETiRet;
}
-
diff --git a/runtime/ratelimit.h b/runtime/ratelimit.h
index a058b06..563777f 100644
--- a/runtime/ratelimit.h
+++ b/runtime/ratelimit.h
@@ -35,6 +35,7 @@ struct ratelimit_s {
unsigned nsupp; /**< nbr of msgs suppressed */
msg_t *pMsg;
sbool bThreadSafe; /**< do we need to operate in Thread-Safe mode? */
+ sbool bNoTimeCache; /**< if we shall not used cached reception time */
pthread_mutex_t mut; /**< mutex if thread-safe operation desired */
};
@@ -42,6 +43,7 @@ struct ratelimit_s {
rsRetVal ratelimitNew(ratelimit_t **ppThis, char *modname, char *dynname);
void ratelimitSetThreadSafe(ratelimit_t *ratelimit);
void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned short interval, unsigned short burst);
+void ratelimitSetNoTimeCache(ratelimit_t *ratelimit);
void ratelimitSetSeverity(ratelimit_t *ratelimit, intTiny severity);
rsRetVal ratelimitMsg(ratelimit_t *ratelimit, msg_t *pMsg, msg_t **ppRep);
rsRetVal ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, msg_t *pMsg);
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 7a8e21c..a8a733d 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -2033,6 +2033,8 @@ int realMain(int argc, char **argv)
ourConf->globals.bErrMsgToStderr = 0;
}
+ sd_notify(0, "READY=1");
+
mainloop();
/* do any de-init's that need to be done AFTER this comment */