summaryrefslogtreecommitdiffstats
path: root/debug.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-04-16 10:26:54 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-04-16 10:26:54 +0200
commit8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc (patch)
tree8bd92ca19ae3cccd5b160c717960db88bb095e73 /debug.c
parent3af28bbd2dc4c79b242aad3b9e3f45cffe0f19d0 (diff)
downloadrsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.gz
rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.xz
rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.zip
moved files to the runtime
there are still some files left which could go into the runtime, but I think we will delete most of them once we are done with the full modularization.
Diffstat (limited to 'debug.c')
-rw-r--r--debug.c1331
1 files changed, 0 insertions, 1331 deletions
diff --git a/debug.c b/debug.c
deleted file mode 100644
index 29c65cf1..00000000
--- a/debug.c
+++ /dev/null
@@ -1,1331 +0,0 @@
-/* debug.c
- *
- * This file proides debug and run time error analysis support. Some of the
- * settings are very performance intense and my be turned off during a release
- * build.
- *
- * File begun on 2008-01-22 by RGerhards
- *
- * Some functions are controlled by environment variables:
- *
- * RSYSLOG_DEBUGLOG if set, a debug log file is written to that location
- * RSYSLOG_DEBUG specific debug options
- *
- * For details, visit doc/debug.html
- *
- * Copyright 2008 Rainer Gerhards and Adiscon GmbH.
- *
- * This file is part of rsyslog.
- *
- * Rsyslog is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Rsyslog is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
- *
- * A copy of the GPL can be found in the file "COPYING" in this distribution.
- */
-#include "config.h" /* autotools! */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <signal.h>
-#include <errno.h>
-#include <pthread.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "rsyslog.h"
-#include "debug.h"
-#include "atomic.h"
-#include "obj.h"
-
-
-/* static data (some time to be replaced) */
-DEFobjCurrIf(obj)
-int Debug; /* debug flag - read-only after startup */
-int debugging_on = 0; /* read-only, except on sig USR1 */
-static int bLogFuncFlow = 0; /* shall the function entry and exit be logged to the debug log? */
-static int bLogAllocFree = 0; /* shall calls to (m/c)alloc and free be logged to the debug log? */
-static int bPrintFuncDBOnExit = 0; /* shall the function entry and exit be logged to the debug log? */
-static int bPrintMutexAction = 0; /* shall mutex calls be printed to the debug log? */
-static int bPrintTime = 1; /* print a timestamp together with debug message */
-static int bPrintAllDebugOnExit = 0;
-static int bAbortTrace = 1; /* print a trace after SIGABRT or SIGSEGV */
-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;
-
-/* 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
- * functions never disappear, we only need to add elements when we see a new one and never need
- * to remove anything. For this, we simply add at the top, which saves us a Last pointer. The goal
- * is to use as few memory as possible.
- */
-typedef struct dbgFuncDBListEntry_s {
- dbgFuncDB_t *pFuncDB;
- struct dbgFuncDBListEntry_s *pNext;
-} dbgFuncDBListEntry_t;
-dbgFuncDBListEntry_t *pFuncDBListRoot;
-
-static pthread_mutex_t mutFuncDBList;
-
-typedef struct dbgMutLog_s {
- struct dbgMutLog_s *pNext;
- struct dbgMutLog_s *pPrev;
- pthread_mutex_t *mut;
- pthread_t thrd;
- dbgFuncDB_t *pFuncDB;
- int lockLn; /* the actual line where the mutex was locked */
- short mutexOp;
-} dbgMutLog_t;
-static dbgMutLog_t *dbgMutLogListRoot = NULL;
-static dbgMutLog_t *dbgMutLogListLast = NULL;
-static pthread_mutex_t mutMutLog;
-
-
-static dbgThrdInfo_t *dbgCallStackListRoot = NULL;
-static dbgThrdInfo_t *dbgCallStackListLast = NULL;
-static pthread_mutex_t mutCallStack;
-
-static pthread_mutex_t mutdbgprintf;
-static pthread_mutex_t mutdbgoprint;
-
-static pthread_key_t keyCallStack;
-
-
-/* we do not have templates, so we use some macros to create linked list handlers
- * for the several types
- * DLL means "doubly linked list"
- * rgerhards, 2008-01-23
- */
-#define DLL_Del(type, pThis) \
- if(pThis->pPrev != NULL) \
- pThis->pPrev->pNext = pThis->pNext; \
- if(pThis->pNext != NULL) \
- pThis->pNext->pPrev = pThis->pPrev; \
- if(pThis == dbg##type##ListRoot) \
- dbg##type##ListRoot = pThis->pNext; \
- if(pThis == dbg##type##ListLast) \
- dbg##type##ListLast = pThis->pPrev; \
- free(pThis);
-
-#define DLL_Add(type, pThis) \
- if(dbg##type##ListRoot == NULL) { \
- dbg##type##ListRoot = pThis; \
- dbg##type##ListLast = pThis; \
- } else { \
- pThis->pPrev = dbg##type##ListLast; \
- dbg##type##ListLast->pNext = pThis; \
- dbg##type##ListLast = pThis; \
- }
-
-/* we need to do our own mutex cancel cleanup handler as it shall not
- * be subject to the debugging instrumentation (that would probably run us
- * into an infinite loop
- */
-static void dbgMutexCancelCleanupHdlr(void *pmut)
-{
- pthread_mutex_unlock((pthread_mutex_t*) pmut);
-}
-
-
-/* handler to update the last execution location seen
- * rgerhards, 2008-01-28
- */
-static inline void
-dbgRecordExecLocation(int iStackPtr, int line)
-{
- dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
- pThrd->lastLine[iStackPtr] = line;
-}
-
-
-/* ------------------------- mutex tracking code ------------------------- */
-
-/* ------------------------- FuncDB utility functions ------------------------- */
-
-#define SIZE_FUNCDB_MUTEX_TABLE(pFuncDB) ((int) (sizeof(pFuncDB->mutInfo) / sizeof(dbgFuncDBmutInfoEntry_t)))
-
-/* print a FuncDB
- */
-static void dbgFuncDBPrint(dbgFuncDB_t *pFuncDB)
-{
- assert(pFuncDB != NULL);
- assert(pFuncDB->magic == dbgFUNCDB_MAGIC);
- /* make output suitable for sorting on invocation count */
- dbgprintf("%10.10ld times called: %s:%d:%s\n", pFuncDB->nTimesCalled, pFuncDB->file, pFuncDB->line, pFuncDB->func);
-}
-
-
-/* print all funcdb entries
- */
-static void dbgFuncDBPrintAll(void)
-{
- dbgFuncDBListEntry_t *pFuncDBList;
- int nFuncs = 0;
-
- for(pFuncDBList = pFuncDBListRoot ; pFuncDBList != NULL ; pFuncDBList = pFuncDBList->pNext) {
- dbgFuncDBPrint(pFuncDBList->pFuncDB);
- nFuncs++;
- }
-
- dbgprintf("%d unique functions called\n", nFuncs);
-}
-
-
-/* find a mutex inside the FuncDB mutex table. Returns NULL if not found. Only mutexes from the same thread
- * are found.
- */
-static inline dbgFuncDBmutInfoEntry_t *dbgFuncDBGetMutexInfo(dbgFuncDB_t *pFuncDB, pthread_mutex_t *pmut)
-{
- int i;
- int iFound = -1;
- pthread_t ourThrd = pthread_self();
-
- for(i = 0 ; i < SIZE_FUNCDB_MUTEX_TABLE(pFuncDB) ; ++i) {
- if(pFuncDB->mutInfo[i].pmut == pmut && pFuncDB->mutInfo[i].lockLn != -1 && pFuncDB->mutInfo[i].thrd == ourThrd) {
- iFound = i;
- break;
- }
- }
-
- return (iFound == -1) ? NULL : &pFuncDB->mutInfo[i];
-}
-
-
-/* print any mutex that can be found in the FuncDB. Custom header is provided.
- * "thrd" is the thread that is searched. If it is 0, mutexes for all threads
- * shall be printed.
- */
-static inline void
-dbgFuncDBPrintActiveMutexes(dbgFuncDB_t *pFuncDB, char *pszHdrText, pthread_t thrd)
-{
- int i;
- char pszThrdName[64];
-
- for(i = 0 ; i < SIZE_FUNCDB_MUTEX_TABLE(pFuncDB) ; ++i) {
- if(pFuncDB->mutInfo[i].lockLn != -1 && (thrd == 0 || thrd == pFuncDB->mutInfo[i].thrd)) {
- dbgGetThrdName(pszThrdName, sizeof(pszThrdName), pFuncDB->mutInfo[i].thrd, 1);
- dbgprintf("%s:%d:%s:invocation %ld: %s %p[%d/%s]\n", pFuncDB->file, pFuncDB->line, pFuncDB->func,
- pFuncDB->mutInfo[i].lInvocation, pszHdrText, (void*)pFuncDB->mutInfo[i].pmut, i,
- pszThrdName);
- }
- }
-}
-
-/* find a free mutex info spot in FuncDB. NULL is returned if table is full.
- */
-static inline dbgFuncDBmutInfoEntry_t *dbgFuncDBFindFreeMutexInfo(dbgFuncDB_t *pFuncDB)
-{
- int i;
- int iFound = -1;
-
- for(i = 0 ; i < SIZE_FUNCDB_MUTEX_TABLE(pFuncDB) ; ++i) {
- if(pFuncDB->mutInfo[i].lockLn == -1) {
- iFound = i;
- break;
- }
- }
-
- if(iFound == -1) {
- dbgprintf("%s:%d:%s: INFO: out of space in FuncDB for mutex info (max %d entries) - ignoring\n",
- pFuncDB->file, pFuncDB->line, pFuncDB->func, SIZE_FUNCDB_MUTEX_TABLE(pFuncDB));
- }
-
- return (iFound == -1) ? NULL : &pFuncDB->mutInfo[i];
-}
-
-/* add a mutex lock to the FuncDB. If the size is exhausted, info is discarded.
- */
-static inline void dbgFuncDBAddMutexLock(dbgFuncDB_t *pFuncDB, pthread_mutex_t *pmut, int lockLn)
-{
- dbgFuncDBmutInfoEntry_t *pMutInfo;
-
- if((pMutInfo = dbgFuncDBFindFreeMutexInfo(pFuncDB)) != NULL) {
- pMutInfo->pmut = pmut;
- pMutInfo->lockLn = lockLn;
- pMutInfo->lInvocation = pFuncDB->nTimesCalled;
- pMutInfo->thrd = pthread_self();
- }
-}
-
-/* remove a locked mutex from the FuncDB (unlock case!).
- */
-static inline void dbgFuncDBRemoveMutexLock(dbgFuncDB_t *pFuncDB, pthread_mutex_t *pmut)
-{
- dbgFuncDBmutInfoEntry_t *pMutInfo;
-
- if((pMutInfo = dbgFuncDBGetMutexInfo(pFuncDB, pmut)) != NULL) {
- pMutInfo->lockLn = -1;
- }
-}
-
-
-/* ------------------------- END FuncDB utility functions ------------------------- */
-
-/* ###########################################################################
- * IMPORTANT NOTE
- * Mutex instrumentation reduces the code's concurrency and thus affects its
- * order of execution. It is vital to test the code also with mutex
- * instrumentation turned off! Some bugs may not show up while it on...
- * ###########################################################################
- */
-
-/* constructor & add new entry to list
- */
-dbgMutLog_t *dbgMutLogAddEntry(pthread_mutex_t *pmut, short mutexOp, dbgFuncDB_t *pFuncDB, int lockLn)
-{
- dbgMutLog_t *pLog;
-
- pLog = calloc(1, sizeof(dbgMutLog_t));
- assert(pLog != NULL);
-
- /* fill data members */
- pLog->mut = pmut;
- pLog->thrd = pthread_self();
- pLog->mutexOp = mutexOp;
- pLog->lockLn = lockLn;
- pLog->pFuncDB = pFuncDB;
-
- DLL_Add(MutLog, pLog);
-
- return pLog;
-}
-
-
-/* destruct log entry
- */
-void dbgMutLogDelEntry(dbgMutLog_t *pLog)
-{
- assert(pLog != NULL);
- DLL_Del(MutLog, pLog);
-}
-
-
-/* print a single mutex log entry */
-static void dbgMutLogPrintOne(dbgMutLog_t *pLog)
-{
- char *strmutop;
- char buf[64];
- char pszThrdName[64];
-
- assert(pLog != NULL);
- switch(pLog->mutexOp) {
- case MUTOP_LOCKWAIT:
- strmutop = "waited on";
- break;
- case MUTOP_LOCK:
- strmutop = "owned";
- break;
- default:
- snprintf(buf, sizeof(buf)/sizeof(char), "unknown state %d - should not happen!", pLog->mutexOp);
- strmutop = buf;
- break;
- }
-
- dbgGetThrdName(pszThrdName, sizeof(pszThrdName), pLog->thrd, 1);
- dbgprintf("mutex 0x%lx is being %s by code at %s:%d, thread %s\n", (unsigned long) pLog->mut,
- strmutop, pLog->pFuncDB->file,
- (pLog->mutexOp == MUTOP_LOCK) ? pLog->lockLn : pLog->pFuncDB->line,
- pszThrdName);
-}
-
-/* print the complete mutex log */
-static void dbgMutLogPrintAll(void)
-{
- dbgMutLog_t *pLog;
-
- dbgprintf("Mutex log for all known mutex operations:\n");
- for(pLog = dbgMutLogListRoot ; pLog != NULL ; pLog = pLog->pNext)
- dbgMutLogPrintOne(pLog);
-
-}
-
-
-/* find the last log entry for that specific mutex object. Is used to delete
- * a thread's own requests. Searches occur from the back.
- * The pFuncDB is optional and may be NULL to indicate no specific funciont is
- * reqested (aka "it is ignored" ;)). This is important for the unlock case.
- */
-dbgMutLog_t *dbgMutLogFindSpecific(pthread_mutex_t *pmut, short mutop, dbgFuncDB_t *pFuncDB)
-{
- dbgMutLog_t *pLog;
- pthread_t mythrd = pthread_self();
-
- pLog = dbgMutLogListLast;
- while(pLog != NULL) {
- if( pLog->mut == pmut && pLog->thrd == mythrd && pLog->mutexOp == mutop
- && (pFuncDB == NULL || pLog->pFuncDB == pFuncDB))
- break;
- pLog = pLog->pPrev;
- }
-
- return pLog;
-}
-
-
-/* find mutex object from the back of the list */
-dbgMutLog_t *dbgMutLogFindFromBack(pthread_mutex_t *pmut, dbgMutLog_t *pLast)
-{
- dbgMutLog_t *pLog;
-
- if(pLast == NULL)
- pLog = dbgMutLogListLast;
- else
- pLog = pLast->pPrev; /* if we get the last processed one, we need to go one before it, else its an endless loop */
-
- while(pLog != NULL) {
- if(pLog->mut == pmut) {
- break;
- }
- pLog = pLog->pPrev;
- }
-
- return pLog;
-}
-
-
-/* find lock aquire for mutex from back of list */
-dbgMutLog_t *dbgMutLogFindHolder(pthread_mutex_t *pmut)
-{
- dbgMutLog_t *pLog;
-
- pLog = dbgMutLogFindFromBack(pmut, NULL);
- while(pLog != NULL) {
- if(pLog->mutexOp == MUTOP_LOCK)
- break;
- pLog = dbgMutLogFindFromBack(pmut, pLog);
- }
-
- return pLog;
-}
-
-/* report wait on a mutex and add it to the mutex log */
-static inline void dbgMutexPreLockLog(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_LOCKWAIT, 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 waiting on lock, held by %s\n", pFuncDB->file, ln, pFuncDB->func, (void*)pmut, pszHolder);
- pthread_mutex_unlock(&mutMutLog);
-}
-
-
-/* report aquired mutex */
-static inline void dbgMutexLockLog(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int lockLn)
-{
- dbgMutLog_t *pLog;
-
- pthread_mutex_lock(&mutMutLog);
-
- /* find and delete "waiting" entry */
- pLog = dbgMutLogFindSpecific(pmut, MUTOP_LOCKWAIT, 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)
-{
- dbgMutLog_t *pLog;
-
- pthread_mutex_lock(&mutMutLog);
- pLog = dbgMutLogFindSpecific(pmut, MUTOP_LOCK, NULL);
- assert(pLog != NULL);
-
- /* we found the last lock entry. We now need to see from which FuncDB we need to
- * remove it. This is recorded inside the mutex log entry.
- */
- dbgFuncDBRemoveMutexLock(pLog->pFuncDB, pmut);
-
- /* donw with the log entry, get rid of it... */
- dbgMutLogDelEntry(pLog);
-
- pthread_mutex_unlock(&mutMutLog);
- if(bPrintMutexAction)
- dbgprintf("%s:%d:%s: mutex %p UNlocked\n", pFuncDB->file, unlockLn, pFuncDB->func, (void*)pmut);
-}
-
-
-/* wrapper for pthread_mutex_lock() */
-int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
-{
- int ret;
-
- dbgRecordExecLocation(iStackPtr, ln);
- dbgMutexPreLockLog(pmut, pFuncDB, ln);
- ret = pthread_mutex_lock(pmut);
- if(ret == 0) {
- dbgMutexLockLog(pmut, pFuncDB, ln);
- } else {
- 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;
-}
-
-
-/* wrapper for pthread_mutex_unlock() */
-int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
-{
- int ret;
- dbgRecordExecLocation(iStackPtr, ln);
- dbgMutexUnlockLog(pmut, pFuncDB, ln);
- ret = pthread_mutex_unlock(pmut);
- return ret;
-}
-
-
-/* wrapper for pthread_cond_wait() */
-int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
-{
- int ret;
- dbgRecordExecLocation(iStackPtr, ln);
- dbgMutexUnlockLog(pmut, pFuncDB, ln);
- if(bPrintMutexAction) {
- dbgprintf("%s:%d:%s: mutex %p waiting on condition %p\n", pFuncDB->file, pFuncDB->line,
- pFuncDB->func, (void*)pmut, (void*)cond);
- }
- dbgMutexPreLockLog(pmut, pFuncDB, ln);
- ret = pthread_cond_wait(cond, pmut);
- return ret;
-}
-
-
-/* wrapper for pthread_cond_timedwait() */
-int dbgCondTimedWait(pthread_cond_t *cond, pthread_mutex_t *pmut, const struct timespec *abstime, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
-{
- int ret;
- dbgRecordExecLocation(iStackPtr, ln);
- dbgMutexUnlockLog(pmut, pFuncDB, ln);
- dbgMutexPreLockLog(pmut, pFuncDB, ln);
- if(bPrintMutexAction) {
- dbgprintf("%s:%d:%s: mutex %p waiting on condition %p (with timeout)\n", pFuncDB->file,
- pFuncDB->line, pFuncDB->func, (void*)pmut, (void*)cond);
- }
- ret = pthread_cond_timedwait(cond, pmut, abstime);
- dbgMutexLockLog(pmut, pFuncDB, ln);
- return ret;
-}
-
-
-/* ------------------------- end mutex tracking code ------------------------- */
-
-
-/* ------------------------- malloc/free tracking code ------------------------- */
-
-/* wrapper for free() */
-void dbgFree(void *pMem, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr)
-{
- dbgRecordExecLocation(iStackPtr, ln);
- if(bLogAllocFree) {
- dbgprintf("%s:%d:%s: free %p\n", pFuncDB->file, ln, pFuncDB->func, (void*) pMem);
- }
- free(pMem);
-}
-
-
-/* ------------------------- end malloc/free tracking code ------------------------- */
-
-/* ------------------------- thread tracking code ------------------------- */
-
-/* get ptr to call stack - if none exists, create a new stack
- */
-static dbgThrdInfo_t *dbgGetThrdInfo(void)
-{
- dbgThrdInfo_t *pThrd;
-
- pthread_mutex_lock(&mutCallStack);
- if((pThrd = pthread_getspecific(keyCallStack)) == NULL) {
- /* construct object */
- pThrd = calloc(1, sizeof(dbgThrdInfo_t));
- pThrd->thrd = pthread_self();
- (void) pthread_setspecific(keyCallStack, pThrd);
- DLL_Add(CallStack, pThrd);
- }
- pthread_mutex_unlock(&mutCallStack);
- return pThrd;
-}
-
-
-
-/* find a specific thread ID. It must be present, else something is wrong
- */
-static inline dbgThrdInfo_t *dbgFindThrd(pthread_t thrd)
-{
- dbgThrdInfo_t *pThrd;
-
- for(pThrd = dbgCallStackListRoot ; pThrd != NULL ; pThrd = pThrd->pNext) {
- if(pThrd->thrd == thrd)
- break;
- }
- return pThrd;
-}
-
-
-/* build a string with the thread name. If none is set, the thread ID is
- * used instead. Caller must provide buffer space. If bIncludeNumID is set
- * to 1, the numerical ID is always included.
- * rgerhards 2008-01-23
- */
-static void dbgGetThrdName(char *pszBuf, size_t lenBuf, pthread_t thrd, int bIncludeNumID)
-{
- dbgThrdInfo_t *pThrd;
-
- assert(pszBuf != NULL);
-
- pThrd = dbgFindThrd(thrd);
-
- if(pThrd == 0 || pThrd->pszThrdName == NULL) {
- /* no thread name, use numeric value */
- snprintf(pszBuf, lenBuf, "%lx", (long) thrd);
- } else {
- if(bIncludeNumID) {
- snprintf(pszBuf, lenBuf, "%s (%lx)", pThrd->pszThrdName, (long) thrd);
- } else {
- snprintf(pszBuf, lenBuf, "%s", pThrd->pszThrdName);
- }
- }
-
-}
-
-
-/* set a name for the current thread. The caller provided string is duplicated.
- */
-void dbgSetThrdName(uchar *pszName)
-{
- dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
- if(pThrd->pszThrdName != NULL)
- free(pThrd->pszThrdName);
- pThrd->pszThrdName = strdup((char*)pszName);
-}
-
-
-/* destructor for a call stack object */
-static void dbgCallStackDestruct(void *arg)
-{
- dbgThrdInfo_t *pThrd = (dbgThrdInfo_t*) arg;
-
- dbgprintf("destructor for debug call stack %p called\n", pThrd);
- if(pThrd->pszThrdName != NULL) {
- free(pThrd->pszThrdName);
- }
-
- pthread_mutex_lock(&mutCallStack);
- DLL_Del(CallStack, pThrd);
- pthread_mutex_unlock(&mutCallStack);
-}
-
-
-/* print a thread's call stack
- */
-static void dbgCallStackPrint(dbgThrdInfo_t *pThrd)
-{
- int i;
- char pszThrdName[64];
-
- pthread_mutex_lock(&mutCallStack);
- dbgGetThrdName(pszThrdName, sizeof(pszThrdName), pThrd->thrd, 1);
- dbgprintf("\n");
- dbgprintf("Recorded Call Order for Thread '%s':\n", pszThrdName);
- for(i = 0 ; i < pThrd->stackPtr ; i++) {
- dbgprintf("%d: %s:%d:%s:\n", i, pThrd->callStack[i]->file, pThrd->lastLine[i], pThrd->callStack[i]->func);
- }
- dbgprintf("maximum number of nested calls for this thread: %d.\n", pThrd->stackPtrMax);
- dbgprintf("NOTE: not all calls may have been recorded, code does not currently guarantee that!\n");
- pthread_mutex_unlock(&mutCallStack);
-}
-
-/* print all threads call stacks
- */
-static void dbgCallStackPrintAll(void)
-{
- dbgThrdInfo_t *pThrd;
- /* stack info */
- for(pThrd = dbgCallStackListRoot ; pThrd != NULL ; pThrd = pThrd->pNext) {
- dbgCallStackPrint(pThrd);
- }
-}
-
-
-/* handler for SIGSEGV - MUST terminiate the app, but does so in a somewhat
- * more meaningful way.
- * rgerhards, 2008-01-22
- */
-void
-sigsegvHdlr(int signum)
-{
- char *signame;
- struct sigaction sigAct;
-
- /* first, restore the default abort handler */
- memset(&sigAct, 0, sizeof (sigAct));
- sigemptyset(&sigAct.sa_mask);
- sigAct.sa_handler = SIG_DFL;
- sigaction(SIGABRT, &sigAct, NULL);
-
- /* then do our actual processing */
- if(signum == SIGSEGV) {
- signame = " (SIGSEGV)";
- } else if(signum == SIGABRT) {
- signame = " (SIGABRT)";
- } else {
- signame = "";
- }
-
- dbgprintf("\n\n\n\nSignal %d%s occured, execution must be terminated.\n\n\n\n", signum, signame);
-
- if(bAbortTrace) {
- dbgPrintAllDebugInfo();
- dbgprintf("If the call trace is empty, you may want to ./configure --enable-rtinst\n");
- dbgprintf("\n\nTo submit bug reports, visit http://www.rsyslog.com/bugs\n\n");
- }
-
- dbgprintf("\n\nTo submit bug reports, visit http://www.rsyslog.com/bugs\n\n");
- if(stddbg != NULL) fflush(stddbg);
- if(altdbg != NULL) fflush(altdbg);
-
- /* and finally abort... */
- /* TODO: think about restarting rsyslog in this case: may be a good idea,
- * but may also be a very bad one (restart loops!)
- */
- abort();
-}
-
-
-/* print some debug output when an object is given
- * This is mostly a copy of dbgprintf, but I do not know how to combine it
- * into a single function as we have variable arguments and I don't know how to call
- * from one vararg function into another. I don't dig in this, it is OK for the
- * time being. -- rgerhards, 2008-01-29
- */
-void
-dbgoprint(obj_t *pObj, char *fmt, ...)
-{
- static pthread_t ptLastThrdID = 0;
- static int bWasNL = 0;
- va_list ap;
- static char pszThrdName[64]; /* 64 is to be on the safe side, anything over 20 is bad... */
- static char pszWriteBuf[1024];
- size_t lenWriteBuf;
- struct timespec t;
-
- if(!(Debug && debugging_on))
- return;
-
- /* a quick and very dirty hack to enable us to display just from those objects
- * that we are interested in. So far, this must be changed at compile time (and
- * chances are great it is commented out while you read it. Later, this shall
- * be selectable via the environment. -- rgerhards, 2008-02-20
- */
-#if 0
- if(objGetObjID(pObj) != OBJexpr)
- return;
-#endif
-
-
- pthread_mutex_lock(&mutdbgoprint);
- pthread_cleanup_push(dbgMutexCancelCleanupHdlr, &mutdbgoprint);
-
- /* The bWasNL handler does not really work. It works if no thread
- * switching occurs during non-NL messages. Else, things are messed
- * up. Anyhow, it works well enough to provide useful help during
- * getting this up and running. It is questionable if the extra effort
- * is worth fixing it, giving the limited appliability.
- * rgerhards, 2005-10-25
- * I have decided that it is not worth fixing it - especially as it works
- * pretty well.
- * rgerhards, 2007-06-15
- */
- if(ptLastThrdID != pthread_self()) {
- if(!bWasNL) {
- if(stddbg != NULL) fprintf(stddbg, "\n");
- if(altdbg != NULL) fprintf(altdbg, "\n");
- bWasNL = 1;
- }
- ptLastThrdID = pthread_self();
- }
-
- /* do not cache the thread name, as the caller might have changed it
- * TODO: optimized, invalidate cache when new name is set
- */
- dbgGetThrdName(pszThrdName, sizeof(pszThrdName), ptLastThrdID, 0);
-
- if(bWasNL) {
- if(bPrintTime) {
- clock_gettime(CLOCK_REALTIME, &t);
- if(stddbg != NULL) fprintf(stddbg, "%4.4ld.%9.9ld:", (long) (t.tv_sec % 10000), t.tv_nsec);
- if(altdbg != NULL) fprintf(altdbg, "%4.4ld.%9.9ld:", (long) (t.tv_sec % 10000), t.tv_nsec);
- }
- if(stddbg != NULL) fprintf(stddbg, "%s: ", pszThrdName);
- if(altdbg != NULL) fprintf(altdbg, "%s: ", pszThrdName);
- /* print object name header if we have an object */
- if(pObj != NULL) {
- if(stddbg != NULL) fprintf(stddbg, "%s: ", obj.GetName(pObj));
- if(altdbg != NULL) fprintf(altdbg, "%s: ", obj.GetName(pObj));
- }
- }
- bWasNL = (*(fmt + strlen(fmt) - 1) == '\n') ? 1 : 0;
- va_start(ap, fmt);
- lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
- if(lenWriteBuf >= sizeof(pszWriteBuf)) {
- /* if our buffer was too small, we simply truncate. TODO: maybe something better? */
- lenWriteBuf = sizeof(pszWriteBuf) - 1;
- }
- va_end(ap);
- /*
- if(stddbg != NULL) fprintf(stddbg, "%s", pszWriteBuf);
- if(altdbg != NULL) fprintf(altdbg, "%s", pszWriteBuf);
- */
- if(stddbg != NULL) fwrite(pszWriteBuf, lenWriteBuf, 1, stddbg);
- if(altdbg != NULL) fwrite(pszWriteBuf, lenWriteBuf, 1, altdbg);
-
- if(stddbg != NULL) fflush(stddbg);
- if(altdbg != NULL) fflush(altdbg);
- pthread_cleanup_pop(1);
-}
-
-
-/* print some debug output when no object is given
- * WARNING: duplicate code, see dbgoprin above!
- */
-void
-dbgprintf(char *fmt, ...)
-{
- static pthread_t ptLastThrdID = 0;
- static int bWasNL = 0;
- va_list ap;
- static char pszThrdName[64]; /* 64 is to be on the safe side, anything over 20 is bad... */
- static char pszWriteBuf[1024];
- size_t lenWriteBuf;
- struct timespec t;
-
- if(!(Debug && debugging_on))
- return;
-
- pthread_mutex_lock(&mutdbgprintf);
- pthread_cleanup_push(dbgMutexCancelCleanupHdlr, &mutdbgprintf);
-
- /* The bWasNL handler does not really work. It works if no thread
- * switching occurs during non-NL messages. Else, things are messed
- * up. Anyhow, it works well enough to provide useful help during
- * getting this up and running. It is questionable if the extra effort
- * is worth fixing it, giving the limited appliability.
- * rgerhards, 2005-10-25
- * I have decided that it is not worth fixing it - especially as it works
- * pretty well.
- * rgerhards, 2007-06-15
- */
- if(ptLastThrdID != pthread_self()) {
- if(!bWasNL) {
- if(stddbg != NULL) fprintf(stddbg, "\n");
- if(altdbg != NULL) fprintf(altdbg, "\n");
- bWasNL = 1;
- }
- ptLastThrdID = pthread_self();
- }
-
- /* do not cache the thread name, as the caller might have changed it
- * TODO: optimized, invalidate cache when new name is set
- */
- dbgGetThrdName(pszThrdName, sizeof(pszThrdName), ptLastThrdID, 0);
-
- if(bWasNL) {
- if(bPrintTime) {
- clock_gettime(CLOCK_REALTIME, &t);
- if(stddbg != NULL) fprintf(stddbg, "%4.4ld.%9.9ld:", (long) (t.tv_sec % 10000), t.tv_nsec);
- if(altdbg != NULL) fprintf(altdbg, "%4.4ld.%9.9ld:", (long) (t.tv_sec % 10000), t.tv_nsec);
- }
- if(stddbg != NULL) fprintf(stddbg, "%s: ", pszThrdName);
- if(altdbg != NULL) fprintf(altdbg, "%s: ", pszThrdName);
- }
- bWasNL = (*(fmt + strlen(fmt) - 1) == '\n') ? 1 : 0;
- va_start(ap, fmt);
- lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap);
- if(lenWriteBuf >= sizeof(pszWriteBuf)) {
- /* if our buffer was too small, we simply truncate. TODO: maybe something better? */
- lenWriteBuf = sizeof(pszWriteBuf) - 1;
- }
- va_end(ap);
- /*
- if(stddbg != NULL) fprintf(stddbg, "%s", pszWriteBuf);
- if(altdbg != NULL) fprintf(altdbg, "%s", pszWriteBuf);
- */
- if(stddbg != NULL) fwrite(pszWriteBuf, lenWriteBuf, 1, stddbg);
- if(altdbg != NULL) fwrite(pszWriteBuf, lenWriteBuf, 1, altdbg);
-
- if(stddbg != NULL) fflush(stddbg);
- if(altdbg != NULL) fflush(altdbg);
- pthread_cleanup_pop(1);
-}
-
-void tester(void)
-{
-BEGINfunc
-ENDfunc
-}
-
-/* handler called when a function is entered. This function creates a new
- * funcDB on the heap if the passed-in pointer is NULL.
- */
-int dbgEntrFunc(dbgFuncDB_t **ppFuncDB, const char *file, const char *func, int line)
-{
- int iStackPtr = 0; /* TODO: find some better default, this one hurts the least, but it is not clean */
- dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
- dbgFuncDBListEntry_t *pFuncDBListEntry;
- unsigned int i;
- dbgFuncDB_t *pFuncDB;
-
- assert(ppFuncDB != NULL);
- assert(file != NULL);
- assert(func != NULL);
- pFuncDB = *ppFuncDB;
- assert((pFuncDB == NULL) || (pFuncDB->magic == dbgFUNCDB_MAGIC));
-
- if(pFuncDB == NULL) {
- /* we do not yet have a funcDB and need to create a new one. We also add it
- * to the linked list of funcDBs. Please note that when a module is unloaded and
- * then reloaded again, we currently do not try to find its previous funcDB but
- * instead create a duplicate. While finding the past one is straightforward, it
- * opens up the question what to do with e.g. mutex data left in it. We do not
- * yet see any need to handle these questions, so duplicaton seems to be the right
- * thing to do. -- rgerhards, 2008-03-10
- */
- /* dbgprintf("%s:%d:%s: called first time, initializing FuncDB\n", pFuncDB->file, pFuncDB->line, pFuncDB->func); */
- /* get a new funcDB and add it to the list (all of this is protected by the mutex) */
- pthread_mutex_lock(&mutFuncDBList);
- if((pFuncDBListEntry = calloc(1, sizeof(dbgFuncDBListEntry_t))) == NULL) {
- dbgprintf("Error %d allocating memory for FuncDB List entry, not adding\n", errno);
- pthread_mutex_unlock(&mutFuncDBList);
- goto exit_it;
- } else {
- if((pFuncDB = calloc(1, sizeof(dbgFuncDB_t))) == NULL) {
- dbgprintf("Error %d allocating memory for FuncDB, not adding\n", errno);
- free(pFuncDBListEntry);
- pthread_mutex_unlock(&mutFuncDBList);
- goto exit_it;
- } else {
- pFuncDBListEntry->pFuncDB = pFuncDB;
- pFuncDBListEntry->pNext = pFuncDBListRoot;
- pFuncDBListRoot = pFuncDBListEntry;
- }
- }
- /* now intialize the funcDB
- * note that we duplicate the strings, because the address provided may go away
- * if a loadable module is unloaded!
- */
- pFuncDB->magic = dbgFUNCDB_MAGIC;
- pFuncDB->file = strdup(file);
- pFuncDB->func = strdup(func);
- pFuncDB->line = line;
- pFuncDB->nTimesCalled = 0;
- for(i = 0 ; i < sizeof(pFuncDB->mutInfo)/sizeof(dbgFuncDBmutInfoEntry_t) ; ++i) {
- pFuncDB->mutInfo[i].lockLn = -1; /* set to not Locked */
- }
-
- /* a round of safety checks... */
- if(pFuncDB->file == NULL || pFuncDB->func == NULL) {
- dbgprintf("Error %d allocating memory for FuncDB, not adding\n", errno);
- /* do a little bit of cleanup */
- if(pFuncDB->file != NULL)
- free(pFuncDB->file);
- if(pFuncDB->func != NULL)
- free(pFuncDB->func);
- free(pFuncDB);
- free(pFuncDBListEntry);
- pthread_mutex_unlock(&mutFuncDBList);
- goto exit_it;
- }
-
- /* done mutex-protected operations */
- pthread_mutex_unlock(&mutFuncDBList);
-
- *ppFuncDB = pFuncDB; /* all went well, so we can update the caller */
- }
-
- /* when we reach this point, we have a fully-initialized FuncDB! */
- ATOMIC_INC(pFuncDB->nTimesCalled);
- 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",
- pFuncDB->file, pFuncDB->line, pFuncDB->func);
- iStackPtr = pThrd->stackPtr;
- } else {
- iStackPtr = pThrd->stackPtr++;
- if(pThrd->stackPtr > pThrd->stackPtrMax)
- pThrd->stackPtrMax = pThrd->stackPtr;
- pThrd->callStack[iStackPtr] = pFuncDB;
- pThrd->lastLine[iStackPtr] = line;
- }
-
-exit_it:
- return iStackPtr;
-}
-
-
-/* handler called when a function is exited
- */
-void dbgExitFunc(dbgFuncDB_t *pFuncDB, int iStackPtrRestore, int iRet)
-{
- dbgThrdInfo_t *pThrd = dbgGetThrdInfo();
-
- assert(iStackPtrRestore >= 0);
- assert(pFuncDB != NULL);
- assert(pFuncDB->magic == dbgFUNCDB_MAGIC);
-
- dbgFuncDBPrintActiveMutexes(pFuncDB, "WARNING: mutex still owned by us as we exit function, mutex: ", pthread_self());
- if(bLogFuncFlow && dbgPrintNameIsInList((const uchar*)pFuncDB->file, printNameFileRoot)) {
- if(iRet == RS_RET_NO_IRET)
- dbgprintf("%s:%d: %s: exit: (no iRet)\n", pFuncDB->file, pFuncDB->line, pFuncDB->func);
- else
- dbgprintf("%s:%d: %s: exit: %d\n", pFuncDB->file, pFuncDB->line, pFuncDB->func, iRet);
- }
- pThrd->stackPtr = iStackPtrRestore;
- if(pThrd->stackPtr < 0) {
- dbgprintf("Stack pointer for thread %lx below 0 - resetting (some RETiRet still wrong!)\n", (long) pthread_self());
- pThrd->stackPtr = 0;
- }
-}
-
-
-/* externally-callable handler to record the last exec location. We use a different function
- * so that the internal one can be inline.
- */
-void
-dbgSetExecLocation(int iStackPtr, int line)
-{
- dbgRecordExecLocation(iStackPtr, line);
-}
-
-
-void dbgPrintAllDebugInfo(void)
-{
- dbgCallStackPrintAll();
- dbgMutLogPrintAll();
- if(bPrintFuncDBOnExit)
- dbgFuncDBPrintAll();
-}
-
-
-/* Handler for SIGUSR2. Dumps all available debug output
- */
-static void sigusr2Hdlr(int __attribute__((unused)) signum)
-{
- dbgprintf("SIGUSR2 received, dumping debug information\n");
- dbgPrintAllDebugInfo();
-}
-
-/* support system to set debug options at runtime */
-
-
-/* parse a param/value pair from the current location of the
- * option string. Returns 1 if an option was found, 0
- * otherwise. 0 means there are NO MORE options to be
- * processed. -- rgerhards, 2008-02-28
- */
-static int
-dbgGetRTOptNamVal(uchar **ppszOpt, uchar **ppOptName, uchar **ppOptVal)
-{
- int bRet = 0;
- uchar *p;
- size_t i;
- static uchar optname[128]; /* not thread- or reentrant-safe, but that */
- static uchar optval[1024]; /* doesn't matter (called only once at startup) */
-
- 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))
- ++p;
-
- /* name - up until '=' or whitespace */
- i = 0;
- while(i < (sizeof(optname)/sizeof(uchar) - 1) && *p && *p != '=' && !isspace(*p)) {
- optname[i++] = *p++;
- }
-
- if(i > 0) {
- bRet = 1;
- optname[i] = '\0';
- if(*p == '=') {
- /* we have a value, get it */
- ++p;
- i = 0;
- while(i < (sizeof(optval)/sizeof(uchar) - 1) && *p && !isspace(*p)) {
- optval[i++] = *p++;
- }
- optval[i] = '\0';
- }
- }
-
- /* done */
- *ppszOpt = p;
- *ppOptName = optname;
- *ppOptVal = optval;
- return bRet;
-}
-
-
-/* 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
- */
-static void
-dbgGetRuntimeOptions(void)
-{
- uchar *pszOpts;
- uchar *optval;
- uchar *optname;
-
- /* set some defaults */
- stddbg = stdout;
-
- if((pszOpts = (uchar*) getenv("RSYSLOG_DEBUG")) != NULL) {
- /* we have options set, so let's process them */
- while(dbgGetRTOptNamVal(&pszOpts, &optname, &optval)) {
- if(!strcasecmp((char*)optname, "help")) {
- fprintf(stderr,
- "rsyslogd runtime debug support - help requested, rsyslog terminates\n\n"
- "environment variables:\n"
- "addional logfile: export RSYSLOG_DEBUGFILE=\"/path/to/file\"\n"
- "to set: export RSYSLOG_DEBUG=\"cmd cmd cmd\"\n\n"
- "Commands are (all case-insensitive):\n"
- "help (this list, terminates rsyslogd\n"
- "LogFuncFlow\n"
- "LogAllocFree (very partly implemented)\n"
- "PrintFuncDB\n"
- "PrintMutexAction\n"
- "PrintAllDebugInfoOnExit (not yet implemented)\n"
- "NoLogTimestamp\n"
- "Nostdoout\n"
- "filetrace=file (may be provided multiple times)\n"
- "\nSee debug.html in your doc set or http://www.rsyslog.com for details\n");
- exit(1);
- } else if(!strcasecmp((char*)optname, "debug")) {
- /* this is earlier in the process than the -d option, as such it
- * allows us to spit out debug messages from the very beginning.
- */
- Debug = 1;
- debugging_on = 1;
- } else if(!strcasecmp((char*)optname, "logfuncflow")) {
- bLogFuncFlow = 1;
- } else if(!strcasecmp((char*)optname, "logallocfree")) {
- bLogAllocFree = 1;
- } else if(!strcasecmp((char*)optname, "printfuncdb")) {
- bPrintFuncDBOnExit = 1;
- } else if(!strcasecmp((char*)optname, "printmutexaction")) {
- bPrintMutexAction = 1;
- } else if(!strcasecmp((char*)optname, "printalldebuginfoonexit")) {
- bPrintAllDebugOnExit = 1;
- } else if(!strcasecmp((char*)optname, "nologtimestamp")) {
- bPrintTime = 0;
- } else if(!strcasecmp((char*)optname, "nostdout")) {
- stddbg = NULL;
- } else if(!strcasecmp((char*)optname, "noaborttrace")) {
- bAbortTrace = 0;
- } 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' - ignored\n",
- optval, optname);
- }
- }
- }
-}
-
-
-/* end support system to set debug options at runtime */
-
-rsRetVal dbgClassInit(void)
-{
- DEFiRet;
-
- struct sigaction sigAct;
- sigset_t sigSet;
-
- (void) pthread_key_create(&keyCallStack, dbgCallStackDestruct); /* MUST be the first action done! */
-
- /* we initialize all Mutexes with code, as some platforms seem to have
- * bugs in the static initializer macros. So better be on the safe side...
- * rgerhards, 2008-03-06
- */
- pthread_mutex_init(&mutFuncDBList, NULL);
- pthread_mutex_init(&mutMutLog, NULL);
- pthread_mutex_init(&mutCallStack, NULL);
- pthread_mutex_init(&mutdbgprintf, NULL);
- pthread_mutex_init(&mutdbgoprint, NULL);
-
- /* while we try not to use any of the real rsyslog code (to avoid infinite loops), we
- * need to have the ability to query object names. Thus, we need to obtain a pointer to
- * the object interface. -- rgerhards, 2008-02-29
- */
- CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
-
- memset(&sigAct, 0, sizeof (sigAct));
- sigemptyset(&sigAct.sa_mask);
- sigAct.sa_handler = sigusr2Hdlr;
- sigaction(SIGUSR2, &sigAct, NULL);
-
- sigemptyset(&sigSet);
- sigaddset(&sigSet, SIGUSR2);
- pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL);
-
- dbgGetRuntimeOptions(); /* init debug system from environment */
- pszAltDbgFileName = getenv("RSYSLOG_DEBUGLOG");
-
- if(pszAltDbgFileName != NULL) {
- /* we have a secondary file, so let's open it) */
- if((altdbg = fopen(pszAltDbgFileName, "w")) == NULL) {
- fprintf(stderr, "alternate debug file could not be opened, ignoring. Error: %s\n", strerror(errno));
- }
- }
-
- dbgSetThrdName((uchar*)"main thread");
-
-finalize_it:
- RETiRet;
-}
-
-
-rsRetVal dbgClassExit(void)
-{
- dbgFuncDBListEntry_t *pFuncDBListEtry, *pToDel;
- pthread_key_delete(keyCallStack);
-
- if(bPrintAllDebugOnExit)
- dbgPrintAllDebugInfo();
-
- if(altdbg != NULL)
- fclose(altdbg);
-
- /* now free all of our memory to make the memory debugger happy... */
- pFuncDBListEtry = pFuncDBListRoot;
- while(pFuncDBListEtry != NULL) {
- pToDel = pFuncDBListEtry;
- pFuncDBListEtry = pFuncDBListEtry->pNext;
- free(pToDel->pFuncDB->file);
- free(pToDel->pFuncDB->func);
- free(pToDel->pFuncDB);
- free(pToDel);
- }
-
- return RS_RET_OK;
-}
-/* vi:set ai:
- */