diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | debug.c | 88 | ||||
-rw-r--r-- | debug.h | 22 |
3 files changed, 78 insertions, 34 deletions
@@ -3,6 +3,8 @@ Version 3.12.2 (rgerhards), 2008-03-?? - added RSYSLOGD_MODDIR environment variable - added -M rsyslogd option (allows to specify module directory location) - converted net.c into a loadable library plugin +- bugfix: debug module now survives unload of loadable module when + printing out function call data --------------------------------------------------------------------------- Version 3.12.1 (rgerhards), 2008-03-06 - added library plugins, which can be automatically loaded @@ -909,42 +909,86 @@ BEGINfunc ENDfunc } -/* handler called when a function is entered +/* 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 *pFuncDB, int line) +int dbgEntrFunc(dbgFuncDB_t **ppFuncDB, const char *file, const char *func, int line) { int iStackPtr; dbgThrdInfo_t *pThrd = dbgGetThrdInfo(); dbgFuncDBListEntry_t *pFuncDBListEntry; unsigned int i; + dbgFuncDB_t *pFuncDB; - assert(pFuncDB != NULL); - assert(pFuncDB->magic == dbgFUNCDB_MAGIC); - - if(pFuncDB->nTimesCalled++ == 0) { - /* dbgprintf("%s:%d:%s: called first time, initializing FuncDB\n", pFuncDB->file, pFuncDB->line, pFuncDB->func); */ - /* this is the first time we see this function, so let's fully initialize the FuncDB. Note - * that partial initialization already occured via the initializer, as far as this could be - * done (all static values have been set). + 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 */ - for(i = 0 ; i < sizeof(pFuncDB->mutInfo)/sizeof(dbgFuncDBmutInfoEntry_t) ; ++i) { - pFuncDB->mutInfo[i].lockLn = -1; /* set to not Locked */ - } - /* finally add element to list of FuncDBs */ + /* 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); - pFuncDB->nTimesCalled = 0; /* retry the next time (OK, quick, but acceptable...) */ + pthread_mutex_unlock(&mutFuncDBList); + goto exit_it; } else { - pFuncDBListEntry->pFuncDB = pFuncDB; - pFuncDBListEntry->pNext = pFuncDBListRoot; - pFuncDBListRoot = pFuncDBListEntry; + 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! */ - + 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*))) { @@ -959,6 +1003,7 @@ int dbgEntrFunc(dbgFuncDB_t *pFuncDB, int line) pThrd->lastLine[iStackPtr] = line; } +exit_it: return iStackPtr; } @@ -1257,15 +1302,12 @@ rsRetVal dbgClassExit(void) { pthread_key_delete(keyCallStack); - /* TODO: implement, this conflicts with module unloads! if(bPrintAllDebugOnExit) dbgPrintAllDebugInfo(); - */ if(altdbg != NULL) fclose(altdbg); return RS_RET_OK; } -/* - * vi:set ai: +/* vi:set ai: */ @@ -49,8 +49,8 @@ typedef struct dbgFuncDBmutInfoEntry_s { typedef struct dbgFuncDB_s { unsigned magic; unsigned long nTimesCalled; - const char *func; - const char *file; + char *func; + char *file; int line; dbgFuncDBmutInfoEntry_t mutInfo[5]; /* remember to update the initializer if you add anything or change the order! */ @@ -92,7 +92,7 @@ int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStac 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); void dbgFree(void *pMem, dbgFuncDB_t *pFuncDB, int ln, int iStackPtr); -int dbgEntrFunc(dbgFuncDB_t *pFuncDB, int line); +int dbgEntrFunc(dbgFuncDB_t **ppFuncDB, const char *file, const char *func, int line); void dbgExitFunc(dbgFuncDB_t *pFuncDB, int iStackPtrRestore, int iRet); void dbgSetExecLocation(int iStackPtr, int line); void dbgSetThrdName(uchar *pszName); @@ -100,9 +100,9 @@ void dbgPrintAllDebugInfo(void); /* macros */ #ifdef RTINST -# define BEGINfunc static dbgFuncDB_t dbgFuncDB=dbgFuncDB_t_INITIALIZER; int dbgCALLStaCK_POP_POINT = dbgEntrFunc(&dbgFuncDB,__LINE__); -# define ENDfunc dbgExitFunc(&dbgFuncDB, dbgCALLStaCK_POP_POINT, RS_RET_NO_IRET); -# define ENDfuncIRet dbgExitFunc(&dbgFuncDB, dbgCALLStaCK_POP_POINT, iRet); +# define BEGINfunc static dbgFuncDB_t *pdbgFuncDB; int dbgCALLStaCK_POP_POINT = dbgEntrFunc(&pdbgFuncDB, __FILE__, __func__, __LINE__); +# define ENDfunc dbgExitFunc(pdbgFuncDB, dbgCALLStaCK_POP_POINT, RS_RET_NO_IRET); +# define ENDfuncIRet dbgExitFunc(pdbgFuncDB, dbgCALLStaCK_POP_POINT, iRet); # define ASSERT(x) assert(x) #else # define BEGINfunc @@ -130,11 +130,11 @@ void dbgPrintAllDebugInfo(void); /* debug aides */ #ifdef RTINST -#define d_pthread_mutex_lock(x) dbgMutexLock(x, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT ) -#define d_pthread_mutex_unlock(x) dbgMutexUnlock(x, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT ) -#define d_pthread_cond_wait(cond, mut) dbgCondWait(cond, mut, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT ) -#define d_pthread_cond_timedwait(cond, mut, to) dbgCondTimedWait(cond, mut, to, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT ) -#define d_free(x) dbgFree(x, &dbgFuncDB, __LINE__, dbgCALLStaCK_POP_POINT ) +#define d_pthread_mutex_lock(x) dbgMutexLock(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_unlock(x) pthread_mutex_unlock(x) |