summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2012-08-22 14:30:12 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2012-08-22 14:30:12 +0200
commitd92ad440da788fea9f17bfa4b0185f12644bf714 (patch)
treedb11db9ced73043ab0f2bf8d02bd49d0abc42191
parent9fb96ec34312b6da7b496db0b3d5eb86442fed06 (diff)
downloadrsyslog-d92ad440da788fea9f17bfa4b0185f12644bf714.zip
rsyslog-d92ad440da788fea9f17bfa4b0185f12644bf714.tar.gz
rsyslog-d92ad440da788fea9f17bfa4b0185f12644bf714.tar.xz
bugfix: multiple main queues with same queue file name were not detected
This lead to queue file corruption. While the root cause is a config error, it is a bug that this important and hard to find config error was not detected by rsyslog.
-rw-r--r--ChangeLog4
-rw-r--r--runtime/ruleset.c6
-rw-r--r--tools/syslogd.c41
3 files changed, 48 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 2efbaa8..32409fd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,10 @@ Version 5.8.13 [V5-stable] 2012-06-??
Thanks to bodik and Rohit Prasad for alerting us on this bug and
analyzing it.
fixes: http://bugzilla.adiscon.com/show_bug.cgi?id=347
+- bugfix: multiple main queues with same queue file name was not detected
+ This lead to queue file corruption. While the root cause is a config
+ error, it is a bug that this important and hard to find config error
+ was not detected by rsyslog.
---------------------------------------------------------------------------
Version 5.8.12 [V5-stable] 2012-06-06
- add small delay (50ms) after sending shutdown message
diff --git a/runtime/ruleset.c b/runtime/ruleset.c
index 8e241c8..d608f3a 100644
--- a/runtime/ruleset.c
+++ b/runtime/ruleset.c
@@ -500,6 +500,7 @@ debugPrintAll(void)
static rsRetVal
rulesetCreateQueue(void __attribute__((unused)) *pVal, int *pNewVal)
{
+ uchar *rsname;
DEFiRet;
if(pCurrRuleset == NULL) {
@@ -517,8 +518,9 @@ rulesetCreateQueue(void __attribute__((unused)) *pVal, int *pNewVal)
if(pNewVal == 0)
FINALIZE; /* if it is turned off, we do not need to change anything ;) */
- dbgprintf("adding a ruleset-specific \"main\" queue");
- CHKiRet(createMainQueue(&pCurrRuleset->pQueue, UCHAR_CONSTANT("ruleset")));
+ rsname = (pCurrRuleset->pszName == NULL) ? (uchar*) "[NONAME]" : pCurrRuleset->pszName;
+ DBGPRINTF("adding a ruleset-specific \"main\" queue for ruleset '%s'\n", rsname);
+ CHKiRet(createMainQueue(&pCurrRuleset->pQueue, rsname));
finalize_it:
RETiRet;
diff --git a/tools/syslogd.c b/tools/syslogd.c
index 8fc1d1e..d8e5032 100644
--- a/tools/syslogd.c
+++ b/tools/syslogd.c
@@ -231,6 +231,11 @@ typedef struct legacyOptsLL_s {
} legacyOptsLL_t;
legacyOptsLL_t *pLegacyOptsLL = NULL;
+struct queuefilenames_s {
+ struct queuefilenames_s *next;
+ uchar *name;
+} *queuefilenames = NULL;
+
/* global variables for config file state */
int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sysklogd. It is
the default, so if no -c<n> option is given, we make ourselvs
@@ -1031,6 +1036,14 @@ static void doDie(int sig)
static void
freeAllDynMemForTermination(void)
{
+ struct queuefilenames_s *qfn, *qfnDel;
+
+ for(qfn = queuefilenames ; qfn != NULL ; ) {
+ qfnDel = qfn;
+ qfn = qfn->next;
+ free(qfnDel->name);
+ free(qfnDel);
+ }
free(pszMainMsgQFName);
free(pModDir);
free(pszConfDAGFile);
@@ -1559,6 +1572,10 @@ startInputModules(void)
*/
rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName)
{
+ struct queuefilenames_s *qfn;
+ uchar *qfname = NULL;
+ static int qfn_renamenum = 0;
+ uchar qfrenamebuf[1024];
DEFiRet;
/* switch the message object to threaded operation, if necessary */
@@ -1584,10 +1601,32 @@ rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName)
errmsg.LogError(0, NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, running with default setting", iRet); \
}
+ if(pszMainMsgQFName != NULL) {
+ /* check if the queue file name is unique, else emit an error */
+ for(qfn = queuefilenames ; qfn != NULL ; qfn = qfn->next) {
+ dbgprintf("check queue file name '%s' vs '%s'\n", qfn->name, pszMainMsgQFName);
+ if(!ustrcmp(qfn->name, pszMainMsgQFName)) {
+ snprintf((char*)qfrenamebuf, sizeof(qfrenamebuf), "%d-%s-%s",
+ ++qfn_renamenum, pszMainMsgQFName,
+ (pszQueueName == NULL) ? "NONAME" : (char*)pszQueueName);
+ qfname = ustrdup(qfrenamebuf);
+ errmsg.LogError(0, NO_ERRCODE, "Error: queue file name '%s' already in use "
+ " - using '%s' instead", pszMainMsgQFName, qfname);
+ break;
+ }
+ }
+ if(qfname == NULL)
+ qfname = ustrdup(pszMainMsgQFName);
+ qfn = malloc(sizeof(struct queuefilenames_s));
+ qfn->name = qfname;
+ qfn->next = queuefilenames;
+ queuefilenames = qfn;
+ }
+
setQPROP(qqueueSetMaxFileSize, "$MainMsgQueueFileSize", iMainMsgQueMaxFileSize);
setQPROP(qqueueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace", iMainMsgQueMaxDiskSpace);
setQPROP(qqueueSetiDeqBatchSize, "$MainMsgQueueDequeueBatchSize", iMainMsgQueDeqBatchSize);
- setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", pszMainMsgQFName);
+ setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", qfname);
setQPROP(qqueueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval", iMainMsgQPersistUpdCnt);
setQPROP(qqueueSetbSyncQueueFiles, "$MainMsgQueueSyncQueueFiles", bMainMsgQSyncQeueFiles);
setQPROP(qqueueSettoQShutdown, "$MainMsgQueueTimeoutShutdown", iMainMsgQtoQShutdown );