diff options
author | Monty <monty@mariadb.org> | 2017-09-05 16:26:29 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-09-08 13:24:42 +0300 |
commit | 0eef1735b6c699fea5c456d3d82574816d157b3d (patch) | |
tree | 0212cc5209c47267f6a5479ebbe251ddb2991140 /dbug | |
parent | 07977c13e71a9fc4a7695facff5fac9d7ff1e870 (diff) | |
download | mariadb-git-0eef1735b6c699fea5c456d3d82574816d157b3d.tar.gz |
Make debug multi thread safe
Fixes crashes in InList when calling _db_set_init (part of SET debug_dbug
in the test suite) from another thread.
Diffstat (limited to 'dbug')
-rw-r--r-- | dbug/dbug.c | 112 |
1 files changed, 87 insertions, 25 deletions
diff --git a/dbug/dbug.c b/dbug/dbug.c index c9d63f527b4..2fe3fbcd761 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -259,7 +259,7 @@ typedef struct _db_code_state_ { #define ListDel(A,B,C) ListAddDel(A,B,C,EXCLUDE) static struct link *ListAddDel(struct link *, const char *, const char *, int); static struct link *ListCopy(struct link *); -static int InList(struct link *linkp,const char *cp, int exact_match); +static int InList(struct link *linkp,const char *cp,int exact_match); static uint ListFlags(struct link *linkp); static void FreeList(struct link *linkp); @@ -458,8 +458,8 @@ static int DbugParse(CODE_STATE *cs, const char *control) if (!(org_cs_locked= cs->locked)) { - cs->locked= 1; pthread_mutex_lock(&THR_LOCK_dbug); + cs->locked= 1; } if (control[0] == '-' && control[1] == '#') @@ -666,8 +666,8 @@ static int DbugParse(CODE_STATE *cs, const char *control) } if (!org_cs_locked) { - pthread_mutex_unlock(&THR_LOCK_dbug); cs->locked= 0; + pthread_mutex_unlock(&THR_LOCK_dbug); } return !rel || f_used; } @@ -1096,7 +1096,7 @@ int _db_explain_init_(char *buf, size_t len) void _db_enter_(const char *_func_, const char *_file_, uint _line_, struct _db_stack_frame_ *_stack_frame_) { - int save_errno; + int save_errno, org_cs_locked; CODE_STATE *cs; if (!((cs=code_state()))) { @@ -1125,12 +1125,20 @@ void _db_enter_(const char *_func_, const char *_file_, cs->stack->flags &= ~SANITY_CHECK_ON; if (TRACING) { - if (!cs->locked) + if (!(org_cs_locked= cs->locked)) + { pthread_mutex_lock(&THR_LOCK_dbug); + cs->locked= 1; + } DoPrefix(cs, _line_); Indent(cs, cs->level); (void) fprintf(cs->stack->out_file->file, ">%s\n", cs->func); DbugFlush(cs); /* This does a unlock */ + if (!org_cs_locked) + { + cs->locked= 0; + pthread_mutex_unlock(&THR_LOCK_dbug); + } } break; case DISABLE_TRACE: @@ -1181,16 +1189,25 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_) if (DoTrace(cs) & DO_TRACE) { + int org_cs_locked; if ((cs->stack->flags & SANITY_CHECK_ON) && sf_sanity()) cs->stack->flags &= ~SANITY_CHECK_ON; if (TRACING) { - if (!cs->locked) + if (!(org_cs_locked= cs->locked)) + { pthread_mutex_lock(&THR_LOCK_dbug); + cs->locked= 1; + } DoPrefix(cs, _stack_frame_->line); Indent(cs, cs->level); (void) fprintf(cs->stack->out_file->file, "<%s\n", cs->func); DbugFlush(cs); + if (!org_cs_locked) + { + cs->locked= 0; + pthread_mutex_unlock(&THR_LOCK_dbug); + } } } /* @@ -1267,14 +1284,17 @@ void _db_doprnt_(const char *format,...) { va_list args; CODE_STATE *cs; - int save_errno; + int save_errno, org_cs_locked; get_code_state_or_return; va_start(args,format); - if (!cs->locked) + if (!(org_cs_locked= cs->locked)) + { pthread_mutex_lock(&THR_LOCK_dbug); + cs->locked= 1; + } save_errno=errno; DoPrefix(cs, cs->u_line); if (TRACING) @@ -1284,6 +1304,11 @@ void _db_doprnt_(const char *format,...) (void) fprintf(cs->stack->out_file->file, "%s: ", cs->u_keyword); DbugVfprintf(cs->stack->out_file->file, format, args); DbugFlush(cs); + if (!org_cs_locked) + { + cs->locked= 0; + pthread_mutex_unlock(&THR_LOCK_dbug); + } errno=save_errno; va_end(args); @@ -1323,12 +1348,15 @@ static void DbugVfprintf(FILE *stream, const char* format, va_list args) void _db_dump_(uint _line_, const char *keyword, const unsigned char *memory, size_t length) { - int pos; + int pos, org_cs_locked; CODE_STATE *cs; get_code_state_or_return; - if (!cs->locked) + if (!(org_cs_locked= cs->locked)) + { pthread_mutex_lock(&THR_LOCK_dbug); + cs->locked= 1; + } if (_db_keyword_(cs, keyword, 0)) { DoPrefix(cs, _line_); @@ -1360,8 +1388,11 @@ void _db_dump_(uint _line_, const char *keyword, (void) fputc('\n',cs->stack->out_file->file); DbugFlush(cs); } - else if (!cs->locked) + if (!org_cs_locked) + { + cs->locked= 0; pthread_mutex_unlock(&THR_LOCK_dbug); + } } @@ -1509,11 +1540,13 @@ static struct link *ListCopy(struct link *orig) static int InList(struct link *linkp, const char *cp, int exact_match) { int result; - for (result=MATCHED; linkp != NULL; linkp= linkp->next_link) { if (!(exact_match ? strcmp(linkp->str,cp) : fnmatch(linkp->str, cp, 0))) - return linkp->flags; + { + result= linkp->flags; + break; + } if (!(linkp->flags & EXCLUDE)) result=NOT_MATCHED; if (linkp->flags & SUBDIR) @@ -1647,6 +1680,7 @@ void _db_end_() FreeState(cs, 0); pthread_mutex_destroy(&THR_LOCK_dbug); init_done= 0; + _dbug_on_= 0; } @@ -1665,22 +1699,39 @@ void _db_end_() static int DoTrace(CODE_STATE *cs) { + int res= DONT_TRACE; + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) && InList(cs->stack->processes, cs->process, 0) & (MATCHED|INCLUDE)) + { switch(InList(cs->stack->functions, cs->func, 0)) { - case INCLUDE|SUBDIR: return ENABLE_TRACE; - case INCLUDE: return DO_TRACE; + case INCLUDE|SUBDIR: + res= ENABLE_TRACE; + break; + case INCLUDE: + res= DO_TRACE; + break; case MATCHED|SUBDIR: case NOT_MATCHED|SUBDIR: - case MATCHED: return framep_trace_flag(cs, cs->framep) ? - DO_TRACE : DONT_TRACE; + case MATCHED: + res= (framep_trace_flag(cs, cs->framep) ? DO_TRACE : DONT_TRACE); + break; case EXCLUDE: - case NOT_MATCHED: return DONT_TRACE; - case EXCLUDE|SUBDIR: return DISABLE_TRACE; + case NOT_MATCHED: + res= DONT_TRACE; + break; + case EXCLUDE|SUBDIR: + res= DISABLE_TRACE; + break; } - return DONT_TRACE; + } + if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); + return res; } + FILE *_db_fp_(void) { CODE_STATE *cs; @@ -1711,10 +1762,17 @@ FILE *_db_fp_(void) BOOLEAN _db_keyword_(CODE_STATE *cs, const char *keyword, int strict) { int match= strict ? INCLUDE : INCLUDE|MATCHED; + int res; get_code_state_if_not_set_or_return FALSE; - return (DEBUGGING && DoTrace(cs) & DO_TRACE && - InList(cs->stack->keywords, keyword, strict) & match); + if (!(DEBUGGING && (DoTrace(cs) & DO_TRACE))) + return 0; + if (!cs->locked) + pthread_mutex_lock(&THR_LOCK_dbug); + res= (InList(cs->stack->keywords, keyword, strict) & match); + if (!cs->locked) + pthread_mutex_unlock(&THR_LOCK_dbug); + return res != 0; } /* @@ -2130,8 +2188,6 @@ static void DbugFlush(CODE_STATE *cs) if (cs->stack->delay) (void) Delay(cs->stack->delay); } - if (!cs->locked) - pthread_mutex_unlock(&THR_LOCK_dbug); } /* DbugFlush */ @@ -2141,9 +2197,15 @@ void _db_flush_() { CODE_STATE *cs; get_code_state_or_return; - (void) fflush(cs->stack->out_file->file); + if (DEBUGGING) + { + pthread_mutex_lock(&THR_LOCK_dbug); + (void) fflush(cs->stack->out_file->file); + pthread_mutex_unlock(&THR_LOCK_dbug); + } } + #ifndef __WIN__ void _db_suicide_() { |