From 89b086855359089ba771d6455cf497be0ae868a7 Mon Sep 17 00:00:00 2001
From: Rainer Gerhards
Date: Wed, 11 Mar 2009 20:40:35 +0100
Subject: added link to (new) online video tutorials to manual set
---
doc/manual.html | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc/manual.html b/doc/manual.html
index 7aebacd8..e7db5768 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -86,6 +86,7 @@ wiki, a community resource which includes rsyslog discussion forum - use this for technical support
+rsyslog video tutorials
rsyslog change log
rsyslog FAQ
syslog device configuration guide (off-site)
--
cgit v1.2.3
From e23e2e391ca1b0a5987b95f1a9f1ec8910faae8a Mon Sep 17 00:00:00 2001
From: Rainer Gerhards
Date: Mon, 16 Mar 2009 10:20:41 +0100
Subject: added link to online tutorial on the web
---
doc/rsyslog_conf.html | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html
index 01e693e4..9855a1b0 100644
--- a/doc/rsyslog_conf.html
+++ b/doc/rsyslog_conf.html
@@ -232,7 +232,11 @@ Lines starting with a hash mark ("#'') and empty lines are ignored.
any
format a user might want. They are also used for dynamic file name
generation. Every output in rsyslog uses templates - this holds true
-for files, user messages and so on. The database writer expects its
+for files, user messages and so on.
+Please note that there is an
+online tutorial on rsyslog templates
+available on the web. We recommend viewing it.
+The database writer expects its
template to be a proper SQL statement - so this is highly customizable
too. You might ask how does all of this work when no templates at all
are specified. Good question ;) The answer is simple, though. Templates
--
cgit v1.2.3
From 16b960939ee44155a9ac6ac6999b6ab71f237034 Mon Sep 17 00:00:00 2001
From: varmojfekoj
Date: Mon, 16 Mar 2009 15:40:03 +0100
Subject: fixed bugs in RainerScript
- when converting a number and a string to a common type, both were
actually converted to the other variable's type.
- the value of rsCStrConvertToNumber() was miscalculated.
Signed-off-by: Rainer Gerhards
---
ChangeLog | 5 +++++
runtime/stringbuf.c | 2 +-
runtime/var.c | 4 ++--
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 35bb29c8..f797f854 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
---------------------------------------------------------------------------
Version 3.20.5 [v3-stable] (rgerhards), 2009-0?-??
+- fixed bugs in RainerScript:
+ o when converting a number and a string to a common type, both were
+ actually converted to the other variable's type.
+ o the value of rsCStrConvertToNumber() was miscalculated.
+ Thanks to varmojfekoj for the patch
- fixed a bug in configure.ac which resulted in problems with
environment detection - thanks to Michael Biebl for the patch
- fixed a potential segfault problem in gssapi code
diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c
index 93d1e1ef..63b42348 100644
--- a/runtime/stringbuf.c
+++ b/runtime/stringbuf.c
@@ -820,7 +820,7 @@ rsCStrConvertToNumber(cstr_t *pStr, number_t *pNumber)
/* TODO: octal? hex? */
n = 0;
while(i < pStr->iStrLen && isdigit(pStr->pBuf[i])) {
- n = n * 10 + pStr->pBuf[i] * 10;
+ n = n * 10 + pStr->pBuf[i] - '0';
++i;
}
diff --git a/runtime/var.c b/runtime/var.c
index 7e51fc6d..f964874b 100644
--- a/runtime/var.c
+++ b/runtime/var.c
@@ -327,7 +327,7 @@ ConvForOperation(var_t *pThis, var_t *pOther)
case VARTYPE_NUMBER:
/* check if we can convert pThis to a number, if so use number format. */
iRet = ConvToNumber(pThis);
- if(iRet != RS_RET_NOT_A_NUMBER) {
+ if(iRet == RS_RET_NOT_A_NUMBER) {
CHKiRet(ConvToString(pOther));
} else {
FINALIZE; /* OK or error */
@@ -345,7 +345,7 @@ ConvForOperation(var_t *pThis, var_t *pOther)
break;
case VARTYPE_STR:
iRet = ConvToNumber(pOther);
- if(iRet != RS_RET_NOT_A_NUMBER) {
+ if(iRet == RS_RET_NOT_A_NUMBER) {
CHKiRet(ConvToString(pThis));
} else {
FINALIZE; /* OK or error */
--
cgit v1.2.3
From 6ffb9010811ee9bc0c3703716443c4dd00922f6f Mon Sep 17 00:00:00 2001
From: Rainer Gerhards
Date: Wed, 25 Mar 2009 17:20:51 +0100
Subject: bugfix: potential abort with DA queue after high watermark is reached
There exists a race condition that can lead to a segfault. Thanks
go to vbernetr, who performed the analysis and provided patch, which
I only tweaked a very little bit.
---
ChangeLog | 4 ++++
runtime/debug.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
runtime/debug.h | 4 ++++
runtime/wti.c | 10 ++++++---
runtime/wtp.c | 20 ++++++++++++++---
runtime/wtp.h | 1 +
6 files changed, 102 insertions(+), 6 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 880f3c73..6becbda9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+- bugfix: potential abort with DA queue after high watermark is reached
+ There exists a race condition that can lead to a segfault. Thanks
+ go to vbernetr, who performed the analysis and provided patch, which
+ I only tweaked a very little bit.
---------------------------------------------------------------------------
Version 3.20.4 [v3-stable] (rgerhards), 2009-02-09
- bugfix: inconsistent use of mutex/atomic operations could cause segfault
diff --git a/runtime/debug.c b/runtime/debug.c
index 1450d029..9d45c737 100644
--- a/runtime/debug.c
+++ b/runtime/debug.c
@@ -473,6 +473,55 @@ static inline void dbgMutexLockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB,
dbgprintf("%s:%d:%s: mutex %p aquired\n", pFuncDB->file, lockLn, pFuncDB->func, (void*)pmut);
}
+
+/* report trylock on a mutex and add it to the mutex log */
+static inline void dbgMutexPreTryLockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln)
+{
+ dbgMutLog_t *pHolder;
+ dbgMutLog_t *pLog;
+ char pszBuf[128];
+ char pszHolderThrdName[64];
+ char *pszHolder;
+
+ pthread_mutex_lock(&mutMutLog);
+ pHolder = dbgMutLogFindHolder(pmut);
+ pLog = dbgMutLogAddEntry(pmut, MUTOP_TRYLOCK, pFuncDB, ln);
+
+ if(pHolder == NULL)
+ pszHolder = "[NONE]";
+ else {
+ dbgGetThrdName(pszHolderThrdName, sizeof(pszHolderThrdName), pHolder->thrd, 1);
+ snprintf(pszBuf, sizeof(pszBuf)/sizeof(char), "%s:%d [%s]", pHolder->pFuncDB->file, pHolder->lockLn, pszHolderThrdName);
+ pszHolder = pszBuf;
+ }
+
+ if(bPrintMutexAction)
+ dbgprintf("%s:%d:%s: mutex %p trying to get lock, held by %s\n", pFuncDB->file, ln, pFuncDB->func, (void*)pmut, pszHolder);
+ pthread_mutex_unlock(&mutMutLog);
+}
+
+
+/* report attempted mutex lock */
+static inline void dbgMutexTryLockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int lockLn)
+{
+ dbgMutLog_t *pLog;
+
+ pthread_mutex_lock(&mutMutLog);
+
+ /* find and delete "trylock" entry */
+ pLog = dbgMutLogFindSpecific(pmut, MUTOP_TRYLOCK, pFuncDB);
+ assert(pLog != NULL);
+ dbgMutLogDelEntry(pLog);
+
+ /* add "lock" entry */
+ pLog = dbgMutLogAddEntry(pmut, MUTOP_LOCK, pFuncDB, lockLn);
+ dbgFuncDBAddMutexLock(pFuncDB, pmut, lockLn);
+ pthread_mutex_unlock(&mutMutLog);
+ if(bPrintMutexAction)
+ dbgprintf("%s:%d:%s: mutex %p aquired\n", pFuncDB->file, lockLn, pFuncDB->func, (void*)pmut);
+}
+
+
/* if we unlock, we just remove the lock aquired entry from the log list */
static inline void dbgMutexUnlockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int unlockLn)
{
@@ -515,6 +564,26 @@ int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStack
}
+/* wrapper for pthread_mutex_trylock() */
+int dbgMutexTryLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
+{
+ int ret;
+
+ dbgRecordExecLocation(iStackPtr, ln);
+ dbgMutexPreLockLog(pmut, pFuncDB, ln); // TODO : update this
+ ret = pthread_mutex_trylock(pmut);
+ if(ret == 0 || ret == EBUSY) {
+ // TODO : update this
+ dbgMutexLockLog(pmut, pFuncDB, ln);
+ } else {
+ dbgprintf("%s:%d:%s: ERROR: pthread_mutex_trylock() for mutex %p failed with error %d\n",
+ pFuncDB->file, ln, pFuncDB->func, (void*)pmut, ret);
+ }
+
+ return ret;
+}
+
+
/* wrapper for pthread_mutex_unlock() */
int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
{
diff --git a/runtime/debug.h b/runtime/debug.h
index 214b7c05..ed914677 100644
--- a/runtime/debug.h
+++ b/runtime/debug.h
@@ -89,6 +89,7 @@ void sigsegvHdlr(int signum);
void dbgoprint(obj_t *pObj, char *fmt, ...) __attribute__((format(printf, 2, 3)));
void dbgprintf(char *fmt, ...) __attribute__((format(printf, 1, 2)));
int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
+int dbgMutexTryLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncD, int ln, int iStackPtr);
@@ -127,17 +128,20 @@ void dbgPrintAllDebugInfo(void);
#define MUTOP_LOCKWAIT 1
#define MUTOP_LOCK 2
#define MUTOP_UNLOCK 3
+#define MUTOP_TRYLOCK 4
/* debug aides */
#ifdef RTINST
#define d_pthread_mutex_lock(x) dbgMutexLock(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
+#define d_pthread_mutex_trylock(x) dbgMutexTryLock(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_mutex_unlock(x) dbgMutexUnlock(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_cond_wait(cond, mut) dbgCondWait(cond, mut, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_pthread_cond_timedwait(cond, mut, to) dbgCondTimedWait(cond, mut, to, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#define d_free(x) dbgFree(x, pdbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT )
#else
#define d_pthread_mutex_lock(x) pthread_mutex_lock(x)
+#define d_pthread_mutex_trylock(x) pthread_mutex_trylock(x)
#define d_pthread_mutex_unlock(x) pthread_mutex_unlock(x)
#define d_pthread_cond_wait(cond, mut) pthread_cond_wait(cond, mut)
#define d_pthread_cond_timedwait(cond, mut, to) pthread_cond_timedwait(cond, mut, to)
diff --git a/runtime/wti.c b/runtime/wti.c
index 13554232..a2531499 100644
--- a/runtime/wti.c
+++ b/runtime/wti.c
@@ -238,10 +238,14 @@ wtiJoinThrd(wti_t *pThis)
ISOBJ_TYPE_assert(pThis, wti);
dbgprintf("waiting for worker %s termination, current state %d\n", wtiGetDbgHdr(pThis), pThis->tCurrCmd);
- pthread_join(pThis->thrdID, NULL);
- wtiSetState(pThis, eWRKTHRD_STOPPED, 0, MUTEX_ALREADY_LOCKED); /* back to virgin... */
- pThis->thrdID = 0; /* invalidate the thread ID so that we do not accidently find reused ones */
+ if (pThis->thrdID == 0) {
+ dbgprintf("worker %s was already stopped\n", wtiGetDbgHdr(pThis));
+ } else {
+ pthread_join(pThis->thrdID, NULL);
+ wtiSetState(pThis, eWRKTHRD_STOPPED, 0, MUTEX_ALREADY_LOCKED); /* back to virgin... */
+ pThis->thrdID = 0; /* invalidate the thread ID so that we do not accidently find reused ones */
dbgprintf("worker %s has stopped\n", wtiGetDbgHdr(pThis));
+ }
RETiRet;
}
diff --git a/runtime/wtp.c b/runtime/wtp.c
index 8b041ea2..fcefa1d8 100644
--- a/runtime/wtp.c
+++ b/runtime/wtp.c
@@ -76,6 +76,7 @@ static rsRetVal NotImplementedDummy() { return RS_RET_OK; }
*/
BEGINobjConstruct(wtp) /* be sure to specify the object type also in END macro! */
pthread_mutex_init(&pThis->mut, NULL);
+ pthread_mutex_init(&pThis->mutThrdShutdwn, NULL);
pthread_cond_init(&pThis->condThrdTrm, NULL);
/* set all function pointers to "not implemented" dummy so that we can safely call them */
pThis->pfChkStopWrkr = NotImplementedDummy;
@@ -140,6 +141,7 @@ CODESTARTobjDestruct(wtp)
/* actual destruction */
pthread_cond_destroy(&pThis->condThrdTrm);
pthread_mutex_destroy(&pThis->mut);
+ pthread_mutex_destroy(&pThis->mutThrdShutdwn);
if(pThis->pszDbgHdr != NULL)
free(pThis->pszDbgHdr);
@@ -189,11 +191,23 @@ wtpProcessThrdChanges(wtp_t *pThis)
if(pThis->bThrdStateChanged == 0)
FINALIZE;
- /* go through all threads */
- for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
- wtiProcessThrdChanges(pThis->pWrkr[i], LOCK_MUTEX);
+ if(d_pthread_mutex_trylock(&(pThis->mutThrdShutdwn)) != 0) {
+ /* another thread is already in the loop */
+ FINALIZE;
}
+ do {
+ /* reset the change marker */
+ pThis->bThrdStateChanged = 0;
+ /* go through all threads */
+ for(i = 0 ; i < pThis->iNumWorkerThreads ; ++i) {
+ wtiProcessThrdChanges(pThis->pWrkr[i], LOCK_MUTEX);
+ }
+ /* restart if another change occured while we were processing the changes */
+ } while(pThis->bThrdStateChanged != 0);
+
+ d_pthread_mutex_unlock(&(pThis->mutThrdShutdwn));
+
finalize_it:
RETiRet;
}
diff --git a/runtime/wtp.h b/runtime/wtp.h
index 13ebe536..0f21ac11 100644
--- a/runtime/wtp.h
+++ b/runtime/wtp.h
@@ -60,6 +60,7 @@ typedef struct wtp_s {
int bInactivityGuard;/* prevents inactivity due to race condition */
rsRetVal (*pConsumer)(void *); /* user-supplied consumer function for dewtpd messages */
/* synchronization variables */
+ pthread_mutex_t mutThrdShutdwn; /* mutex to guard thread shutdown processing */
pthread_mutex_t mut; /* mutex for the wtp's thread management */
pthread_cond_t condThrdTrm;/* signalled when threads terminate */
int bThrdStateChanged; /* at least one thread state has changed if 1 */
--
cgit v1.2.3
From 01adeab0cba21ad6193addf1a4e90689b507d092 Mon Sep 17 00:00:00 2001
From: Rainer Gerhards
Date: Thu, 2 Apr 2009 14:41:32 +0200
Subject: preparing for 3.20.5 release
---
ChangeLog | 4 ++--
configure.ac | 2 +-
doc/manual.html | 2 +-
runtime/wtp.c | 8 ++++++++
4 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index a94eb24a..a4eb6151 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,9 @@
+---------------------------------------------------------------------------
+Version 3.20.5 [v3-stable] (rgerhards), 2009-04-02
- bugfix: potential abort with DA queue after high watermark is reached
There exists a race condition that can lead to a segfault. Thanks
go to vbernetr, who performed the analysis and provided patch, which
I only tweaked a very little bit.
----------------------------------------------------------------------------
-Version 3.20.5 [v3-stable] (rgerhards), 2009-0?-??
- fixed bugs in RainerScript:
o when converting a number and a string to a common type, both were
actually converted to the other variable's type.
diff --git a/configure.ac b/configure.ac
index 6a79d9a3..e636070c 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],[3.20.4],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[3.20.5],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([ChangeLog])
AC_CONFIG_HEADERS([config.h])
diff --git a/doc/manual.html b/doc/manual.html
index e7db5768..c9fd9b90 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -16,7 +16,7 @@ relay chains while at the same time being very easy to setup for the
novice user. And as we know what enterprise users really need, there is
also professional
rsyslog support available directly from the source!
-This documentation is for version 3.20.4 (v3-stable branch) of rsyslog.
+
This documentation is for version 3.20.5 (v3-stable branch) of rsyslog.
Visit the rsyslog status page to obtain current
version information and project status.
If you like rsyslog, you might
diff --git a/runtime/wtp.c b/runtime/wtp.c
index fcefa1d8..3e3ff09a 100644
--- a/runtime/wtp.c
+++ b/runtime/wtp.c
@@ -196,6 +196,14 @@ wtpProcessThrdChanges(wtp_t *pThis)
FINALIZE;
}
+ /* Note: there is a left-over potential race condition below:
+ * pThis->bThrdStateChanged may be re-set by another thread while
+ * we work on it and thus the loop may terminate too early. However,
+ * there are no really bad effects from that so I perfer - for this
+ * version - to live with the problem as is. Not a good idea to
+ * introduce that large change into the stable branch without very
+ * good reason. -- rgerhards, 2009-04-02
+ */
do {
/* reset the change marker */
pThis->bThrdStateChanged = 0;
--
cgit v1.2.3