From 29dd634a4c0b9c3579cf9d318ed64d748d848b1d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 10 Nov 2015 16:57:15 +0100 Subject: [PATCH] dbug: correct trace for DBUG_RETURN(func()); -- gcc only when func1 calls func2 from DBUG_RETURN, dbug shows the trace as | > func1 | < func1 | > func2 | < func2 because DBUG_LEAVE happens before func2(). Change that to invoke DBUG_LEAVE when the local variable goes out of scope. This uses gcc specific __attribute__((cleanup)). --- cmake/os/WindowsCache.cmake | 1 + config.h.cmake | 2 +- configure.cmake | 8 ++++++++ dbug/dbug.c | 10 +++++++--- include/my_dbug.h | 19 ++++++++++++++++--- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/cmake/os/WindowsCache.cmake b/cmake/os/WindowsCache.cmake index b043b174e783e..86c1e425f0c14 100644 --- a/cmake/os/WindowsCache.cmake +++ b/cmake/os/WindowsCache.cmake @@ -320,6 +320,7 @@ IF(MSVC_VERSION GREATER 1310) SET(HAVE_VSNPRINTF 1 CACHE INTERNAL "") ENDIF() SET(HAVE_WEAK_SYMBOL CACHE INTERNAL "") +SET(HAVE_ATTRIBUTE_CLEANUP CACHE INTERNAL "") SET(HAVE_WORDS_BIGENDIAN TRUE CACHE INTERNAL "") SET(WORDS_BIGENDIAN CACHE INTERNAL "") SET(HAVE__S_IFIFO 1 CACHE INTERNAL "") diff --git a/config.h.cmake b/config.h.cmake index c0eaad29cb11a..96165c16aa0f6 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -465,7 +465,7 @@ #cmakedefine HAVE_WEAK_SYMBOL 1 #cmakedefine HAVE_ABI_CXA_DEMANGLE 1 - +#cmakedefine HAVE_ATTRIBUTE_CLEANUP 1 #cmakedefine HAVE_POSIX_SIGNALS 1 #cmakedefine HAVE_BSD_SIGNALS 1 diff --git a/configure.cmake b/configure.cmake index 1dade02aa3299..e8d29c5bf5fc0 100644 --- a/configure.cmake +++ b/configure.cmake @@ -910,6 +910,14 @@ CHECK_C_SOURCE_COMPILES(" HAVE_WEAK_SYMBOL ) +CHECK_C_SOURCE_COMPILES(" + void foo(int *x) { } + int main() { + int a __attribute__((cleanup(foo))); + return 0; + }" + HAVE_ATTRIBUTE_CLEANUP +) CHECK_CXX_SOURCE_COMPILES(" #include diff --git a/dbug/dbug.c b/dbug/dbug.c index dffd7a44cd8f0..b2b298beb096d 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -1106,6 +1106,7 @@ void _db_enter_(const char *_func_, const char *_file_, } save_errno= errno; + _stack_frame_->line= -1; _stack_frame_->func= cs->func; _stack_frame_->file= cs->file; cs->func= _func_; @@ -1161,14 +1162,17 @@ void _db_enter_(const char *_func_, const char *_file_, * */ -void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) +void _db_return_(struct _db_stack_frame_ *_stack_frame_) { int save_errno=errno; uint _slevel_= _stack_frame_->level & ~TRACE_ON; CODE_STATE *cs; get_code_state_or_return; - if (cs->framep != _stack_frame_) + if (_stack_frame_->line == 0) + return; + + if (_stack_frame_->line == -1 || cs->framep != _stack_frame_) { char buf[512]; my_snprintf(buf, sizeof(buf), ERR_MISSING_RETURN, cs->func); @@ -1183,7 +1187,7 @@ void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_) { if (!cs->locked) pthread_mutex_lock(&THR_LOCK_dbug); - DoPrefix(cs, _line_); + DoPrefix(cs, _stack_frame_->line); Indent(cs, cs->level); (void) fprintf(cs->stack->out_file->file, "<%s\n", cs->func); DbugFlush(cs); diff --git a/include/my_dbug.h b/include/my_dbug.h index f4c854bc10cc8..d56033ab02525 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -30,6 +30,7 @@ struct _db_stack_frame_ { const char *func; /* function name of the previous stack frame */ const char *file; /* filename of the function of previous frame */ uint level; /* this nesting level, highest bit enables tracing */ + int line; /* line of DBUG_RETURN */ struct _db_stack_frame_ *prev; /* pointer to the previous frame */ }; @@ -48,7 +49,7 @@ extern void _db_set_(const char *control); extern void _db_set_init_(const char *control); extern void _db_enter_(const char *_func_, const char *_file_, uint _line_, struct _db_stack_frame_ *_stack_frame_); -extern void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_); +extern void _db_return_(struct _db_stack_frame_ *_stack_frame_); extern void _db_pargs_(uint _line_,const char *keyword); extern void _db_doprnt_(const char *format,...) ATTRIBUTE_FORMAT(printf, 1, 2); @@ -63,12 +64,24 @@ extern void dbug_swap_code_state(void **code_state_store); extern void dbug_free_code_state(void **code_state_store); extern const char* _db_get_func_(void); +#define DBUG_LEAVE do { \ + _db_stack_frame_.line= __LINE__; \ + _db_return_ (&_db_stack_frame_); \ + _db_stack_frame_.line= 0; \ + } while(0) + +#ifdef HAVE_ATTRIBUTE_CLEANUP +#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_ __attribute__((cleanup(_db_return_))); \ + _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_) +#define DBUG_RETURN(a1) do { _db_stack_frame_.line=__LINE__; return(a1);} while(0) +#define DBUG_VOID_RETURN do { _db_stack_frame_.line=__LINE__; return;} while(0) +#else #define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \ _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_) -#define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_) - #define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0) #define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0) +#endif + #define DBUG_EXECUTE(keyword,a1) \ do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0) #define DBUG_EXECUTE_IF(keyword,a1) \