summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-02-28 15:58:06 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2008-02-28 15:58:06 +0000
commit0621b1339d7b308a89356a9201eba4562a58085d (patch)
tree859bcb3d8e30f3c883cedec2b1f1684c151158cc
parente06557a4cd02069579a8af060a461b88a676caab (diff)
downloadrsyslog-0621b1339d7b308a89356a9201eba4562a58085d.tar.gz
rsyslog-0621b1339d7b308a89356a9201eba4562a58085d.tar.xz
rsyslog-0621b1339d7b308a89356a9201eba4562a58085d.zip
enabled debug-support to pull runtime options from environment (bug 18)
-rw-r--r--debug.c115
-rw-r--r--doc/debug.html6
2 files changed, 95 insertions, 26 deletions
diff --git a/debug.c b/debug.c
index 9e8ebc0e..110fa09c 100644
--- a/debug.c
+++ b/debug.c
@@ -8,12 +8,10 @@
*
* Some functions are controlled by environment variables:
*
- * RSYSLOG_DEBUGLOG * if set, a debug log file is written
- * to that location
+ * RSYSLOG_DEBUGLOG if set, a debug log file is written to that location
+ * RSYSLOG_DEBUG specific debug options
*
- * There is some in-depth documentation available in doc/dev_queue.html
- * (and in the web doc set on http://www.rsyslog.com/doc). Be sure to read it
- * if you are getting aquainted to the object.
+ * For details, visit doc/debug.html
*
* Copyright 2008 Rainer Gerhards and Adiscon GmbH.
*
@@ -51,9 +49,6 @@
#include "debug.h"
#include "obj.h"
-/* forward definitions */
-static void dbgGetThrdName(char *pszBuf, size_t lenBuf, pthread_t thrd, int bIncludeNumID);
-static dbgThrdInfo_t *dbgGetThrdInfo(void);
/* static data (some time to be replaced) */
int Debug; /* debug flag - read-only after startup */
@@ -67,7 +62,22 @@ static int bPrintAllDebugOnExit = 0;
static char *pszAltDbgFileName = NULL; /* if set, debug output is *also* sent to here */
static FILE *altdbg = NULL; /* and the handle for alternate debug output */
static FILE *stddbg;
-//static dbgFuncDB_t pCurrFunc;
+
+/* list of files/objects that should be printed */
+typedef struct dbgPrintName_s {
+ uchar *pName;
+ struct dbgPrintName_s *pNext;
+} dbgPrintName_t;
+
+
+/* forward definitions */
+static void dbgGetThrdName(char *pszBuf, size_t lenBuf, pthread_t thrd, int bIncludeNumID);
+static dbgThrdInfo_t *dbgGetThrdInfo(void);
+static int dbgPrintNameIsInList(const uchar *pName, dbgPrintName_t *pRoot);
+
+
+/* This lists are single-linked and members are added at the top */
+static dbgPrintName_t *printNameFileRoot = NULL;
/* list of all known FuncDBs. We use a special list, because it must only be single-linked. As
@@ -272,7 +282,6 @@ static inline void dbgFuncDBRemoveMutexLock(dbgFuncDB_t *pFuncDB, pthread_mutex_
if((pMutInfo = dbgFuncDBGetMutexInfo(pFuncDB, pmut)) != NULL) {
pMutInfo->lockLn = -1;
}
-//dbgprintf("dbgFuncDB mutex to be removed %p, ptr found %p, lockLn %d\n", pmut, pMutInfo, (pMutInfo == 0) ? 123456789 : pMutInfo->lockLn);
}
@@ -496,8 +505,8 @@ int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStack
if(ret == 0) {
dbgMutexLockLog(pmut, pFuncDB, ln);
} else {
- dbgprintf("%s:%d:%s: ERROR: pthread_mutex_lock() for mutex %p failed with error %d (%s)\n",
- pFuncDB->file, ln, pFuncDB->func, (void*)pmut, ret, strerror(errno)); // TODO: remove strerror!"!!
+ dbgprintf("%s:%d:%s: ERROR: pthread_mutex_lock() for mutex %p failed with error %d\n",
+ pFuncDB->file, ln, pFuncDB->func, (void*)pmut, ret);
}
return ret;
@@ -931,12 +940,7 @@ int dbgEntrFunc(dbgFuncDB_t *pFuncDB, int line)
/* when we reach this point, we have a fully-initialized FuncDB! */
- //if(bLogFuncFlow) /* quick debug hack... select the best for you! */
- if(bLogFuncFlow && !strcmp((char*)pFuncDB->file, "vm.c")) /* quick debug hack... select the best for you! */
- //if(bLogFuncFlow && !strcmp((char*)pFuncDB->file, "expr.c")) /* quick debug hack... select the best for you! */
- //if(bLogFuncFlow && (!strcmp((char*)pFuncDB->file, "wti.c")
- //||!strcmp((char*)pFuncDB->file, "wtp.c")
- //||!strcmp((char*)pFuncDB->file, "queue.c"))) /* quick debug hack... select the best for you! */
+ if(bLogFuncFlow && dbgPrintNameIsInList((const uchar*)pFuncDB->file, printNameFileRoot))
dbgprintf("%s:%d: %s: enter\n", pFuncDB->file, pFuncDB->line, pFuncDB->func);
if(pThrd->stackPtr >= (int) (sizeof(pThrd->callStack) / sizeof(dbgFuncDB_t*))) {
dbgprintf("%s:%d: %s: debug module: call stack for this thread full, suspending call tracking\n",
@@ -965,12 +969,7 @@ void dbgExitFunc(dbgFuncDB_t *pFuncDB, int iStackPtrRestore)
assert(pFuncDB->magic == dbgFUNCDB_MAGIC);
dbgFuncDBPrintActiveMutexes(pFuncDB, "WARNING: mutex still owned by us as we exit function, mutex: ", pthread_self());
- //if(bLogFuncFlow) /* quick debug hack... select the best for you! */
- if(bLogFuncFlow && !strcmp((char*)pFuncDB->file, "vm.c")) /* quick debug hack... select the best for you! */
- //if(bLogFuncFlow && !strcmp((char*)pFuncDB->file, "expr.c")) /* quick debug hack... select the best for you! */
- //if(bLogFuncFlow && (!strcmp((char*)pFuncDB->file, "wti.c")
- //||!strcmp((char*)pFuncDB->file, "wtp.c")
- //||!strcmp((char*)pFuncDB->file, "queue.c"))) /* quick debug hack... select the best for you! */
+ if(bLogFuncFlow && dbgPrintNameIsInList((const uchar*)pFuncDB->file, printNameFileRoot))
dbgprintf("%s:%d: %s: exit\n", pFuncDB->file, pFuncDB->line, pFuncDB->func);
pThrd->stackPtr = iStackPtrRestore;
if(pThrd->stackPtr < 0) {
@@ -1027,6 +1026,10 @@ dbgGetRTOptNamVal(uchar **ppszOpt, uchar **ppOptName, uchar **ppOptVal)
assert(ppszOpt != NULL);
assert(*ppszOpt != NULL);
+ /* make sure we have some initial values */
+ optname[0] = '\0';
+ optval[0] = '\0';
+
p = *ppszOpt;
/* skip whitespace */
while(*p && isspace(*p))
@@ -1060,6 +1063,60 @@ dbgGetRTOptNamVal(uchar **ppszOpt, uchar **ppOptName, uchar **ppOptVal)
}
+/* create new PrintName list entry and add it to list (they will never
+ * be removed. -- rgerhards, 2008-02-28
+ */
+static void
+dbgPrintNameAdd(uchar *pName, dbgPrintName_t **ppRoot)
+{
+ dbgPrintName_t *pEntry;
+
+ if((pEntry = calloc(1, sizeof(dbgPrintName_t))) == NULL) {
+ fprintf(stderr, "ERROR: out of memory during debug setup\n");
+ exit(1);
+ }
+
+ if((pEntry->pName = (uchar*) strdup((char*) pName)) == NULL) {
+ fprintf(stderr, "ERROR: out of memory during debug setup\n");
+ exit(1);
+ }
+
+ if(*ppRoot != NULL) {
+ pEntry->pNext = *ppRoot; /* we enqueue at the front */
+ }
+ *ppRoot = pEntry;
+
+printf("Name %s added to %p\n", pName, *ppRoot);
+}
+
+
+/* check if name is in a printName list - returns 1 if so, 0 otherwise.
+ * There is one special handling: if the root pointer is NULL, the function
+ * always returns 1. This is because when no name is set, output shall be
+ * unrestricted.
+ * rgerhards, 2008-02-28
+ */
+static int
+dbgPrintNameIsInList(const uchar *pName, dbgPrintName_t *pRoot)
+{
+ int bFound = 0;
+ dbgPrintName_t *pEntry = pRoot;
+
+ if(pRoot == NULL)
+ bFound = 1;
+
+ while(pEntry != NULL && !bFound) {
+ if(!strcasecmp((char*)pEntry->pName, (char*)pName)) {
+ bFound = 1;
+ } else {
+ pEntry = pEntry->pNext;
+ }
+ }
+
+ return bFound;
+}
+
+
/* read in the runtime options
* rgerhards, 2008-02-28
*/
@@ -1076,7 +1133,6 @@ dbgGetRuntimeOptions(void)
if((pszOpts = (uchar*) getenv("RSYSLOG_DEBUG")) != NULL) {
/* we have options set, so let's process them */
while(dbgGetRTOptNamVal(&pszOpts, &optname, &optval)) {
-//TODO: remove printf("option %s val %s found\n", optname, optval);
if(!strcasecmp((char*)optname, "logfuncflow")) {
bLogFuncFlow = 1;
} else if(!strcasecmp((char*)optname, "logallocfree")) {
@@ -1091,6 +1147,15 @@ dbgGetRuntimeOptions(void)
bPrintTime = 0;
} else if(!strcasecmp((char*)optname, "nostdout")) {
stddbg = NULL;
+ } else if(!strcasecmp((char*)optname, "filetrace")) {
+ if(*optval == '\0') {
+ fprintf(stderr, "Error: logfile debug option requires filename, "
+ "e.g. \"logfile=debug.c\"\n");
+ exit(1);
+ } else {
+ /* create new entry and add it to list */
+ dbgPrintNameAdd(optval, &printNameFileRoot);
+ }
} else {
fprintf(stderr, "Error: invalid debug option '%s', value '%s'\n",
optval, optname);
diff --git a/doc/debug.html b/doc/debug.html
index d4f00e53..ae163eb4 100644
--- a/doc/debug.html
+++ b/doc/debug.html
@@ -23,7 +23,11 @@ all debug message to the specified log file in addition to stdout. Some
system messages (e.g. segfault or abort message) are not written to the
file as we can not capture them. Runtime debug support is controlled by
"RSYSLOG_DEBUG". It contains an option string with the following
-options possible (all are case insensitive):</p><ul><li><span style="font-weight: bold;">LogFuncFlow</span> - print out the logical flow of functions (entering and exiting them)</li><li><span style="font-weight: bold;">PrintFuncDB</span> - print the content of the debug function database whenever debug information is printed (e.g. abort case)!</li><li><span style="font-weight: bold;">PrintAllDebugInfoOnExit</span> - print all debug information immediately before rsyslogd exits (<span style="font-weight: bold; font-style: italic;">currently not implemented!</span>)</li><li><span style="font-weight: bold;">PrintMutexAction</span> - print mutex action as it happens. Useful for finding deadlocks and such.</li><li><span style="font-weight: bold;">NoLogTimeStamp</span> - do not prefix log lines with a timestamp (default is to do that).</li><li><span style="font-weight: bold;">NoStdOut</span> - do not emit debug messages to stdout. If RSYSLOG_DEBUGLOG is not set, this means no messages will be displayed at all.</li></ul>
+options possible (all are case insensitive):</p><ul><li><span style="font-weight: bold;">LogFuncFlow</span> - print out the logical flow of functions (entering and exiting them)</li><li><span style="font-weight: bold;">FileTrace</span> - specifies which files to trace LogFuncFlow. If <span style="font-weight: bold;">not</span>
+set (the default), a LogFuncFlow trace is provided for all files. Set
+to limit it to the files specified. FileTrace may be specified multiple
+times, one file each (e.g. export RSYSLOG_DEBUG="LogFuncFlow
+FileTrace=vm.c FileTrace=expr.c"</li><li><span style="font-weight: bold;">PrintFuncDB</span> - print the content of the debug function database whenever debug information is printed (e.g. abort case)!</li><li><span style="font-weight: bold;">PrintAllDebugInfoOnExit</span> - print all debug information immediately before rsyslogd exits (<span style="font-weight: bold; font-style: italic;">currently not implemented!</span>)</li><li><span style="font-weight: bold;">PrintMutexAction</span> - print mutex action as it happens. Useful for finding deadlocks and such.</li><li><span style="font-weight: bold;">NoLogTimeStamp</span> - do not prefix log lines with a timestamp (default is to do that).</li><li><span style="font-weight: bold;">NoStdOut</span> - do not emit debug messages to stdout. If RSYSLOG_DEBUGLOG is not set, this means no messages will be displayed at all.</li></ul>
<ul>
</ul>
<p>[<a href="manual.html">manual index</a>] [<a href="http://www.rsyslog.com/">rsyslog site</a>]</p>