1/* Copyright (c) 2000, 2010, Oracle and/or its affiliates.
2 Copyright (C) 2000, 2017, MariaDB Corporation Ab
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17#ifndef _my_dbug_h
18#define _my_dbug_h
19
20#ifndef __WIN__
21#include <signal.h>
22#endif /* not __WIN__ */
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27#if !defined(DBUG_OFF) && !defined(_lint)
28
29struct _db_stack_frame_ {
30 const char *func; /* function name of the previous stack frame */
31 const char *file; /* filename of the function of previous frame */
32 uint level; /* this nesting level, highest bit enables tracing */
33 int line; /* line of DBUG_RETURN */
34 struct _db_stack_frame_ *prev; /* pointer to the previous frame */
35};
36
37struct _db_code_state_;
38extern my_bool _dbug_on_;
39extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int);
40extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len);
41extern int _db_explain_init_(char *buf, size_t len);
42extern int _db_is_pushed_(void);
43extern void _db_setjmp_(void);
44extern void _db_longjmp_(void);
45extern void _db_process_(const char *name);
46extern void _db_push_(const char *control);
47extern void _db_pop_(void);
48extern void _db_set_(const char *control);
49extern void _db_set_init_(const char *control);
50extern void _db_enter_(const char *_func_, const char *_file_, uint _line_,
51 struct _db_stack_frame_ *_stack_frame_);
52extern void _db_return_(struct _db_stack_frame_ *_stack_frame_);
53extern int _db_pargs_(uint _line_,const char *keyword);
54extern void _db_doprnt_(const char *format,...)
55 ATTRIBUTE_FORMAT(printf, 1, 2);
56extern void _db_dump_(uint _line_,const char *keyword,
57 const unsigned char *memory, size_t length);
58extern void _db_end_(void);
59extern void _db_lock_file_(void);
60extern void _db_unlock_file_(void);
61extern FILE *_db_fp_(void);
62extern void _db_flush_(void);
63extern void dbug_swap_code_state(void **code_state_store);
64extern void dbug_free_code_state(void **code_state_store);
65extern const char* _db_get_func_(void);
66extern int (*dbug_sanity)(void);
67
68#define DBUG_LEAVE do { \
69 _db_stack_frame_.line= __LINE__; \
70 _db_return_ (&_db_stack_frame_); \
71 _db_stack_frame_.line= 0; \
72 } while(0)
73
74#ifdef HAVE_ATTRIBUTE_CLEANUP
75#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_ __attribute__((cleanup(_db_return_))); \
76 _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
77#define DBUG_RETURN(a1) do { _db_stack_frame_.line=__LINE__; return(a1);} while(0)
78#define DBUG_VOID_RETURN do { _db_stack_frame_.line=__LINE__; return;} while(0)
79#else
80#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \
81 _db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
82#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
83#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
84#endif
85
86#define DBUG_EXECUTE(keyword,a1) \
87 do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0)
88#define DBUG_EXECUTE_IF(keyword,a1) \
89 do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0)
90#define DBUG_EVALUATE(keyword,a1,a2) \
91 (_db_keyword_(0,(keyword), 0) ? (a1) : (a2))
92#define DBUG_EVALUATE_IF(keyword,a1,a2) \
93 (_db_keyword_(0,(keyword), 1) ? (a1) : (a2))
94#define DBUG_PRINT(keyword,arglist) \
95 do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0)
96#define DBUG_PUSH(a1) _db_push_ (a1)
97#define DBUG_POP() _db_pop_ ()
98#define DBUG_SET(a1) _db_set_ (a1)
99#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1)
100#define DBUG_PROCESS(a1) _db_process_(a1)
101#define DBUG_FILE _db_fp_()
102#define DBUG_DUMP(keyword,a1,a2) _db_dump_(__LINE__,keyword,a1,a2)
103#define DBUG_END() _db_end_ ()
104#define DBUG_LOCK_FILE _db_lock_file_()
105#define DBUG_UNLOCK_FILE _db_unlock_file_()
106#define DBUG_ASSERT(A) do { if (!(A)) { _db_flush_(); assert(A); }} while (0)
107#define DBUG_SLOW_ASSERT(A) DBUG_ASSERT(A)
108#define DBUG_ASSERT_EXISTS
109#define DBUG_EXPLAIN(buf,len) _db_explain_(0, (buf),(len))
110#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len))
111#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0)
112#define DEBUGGER_ON do { _dbug_on_= 1; } while(0)
113#define IF_DBUG(A,B) A
114#define IF_DBUG_ASSERT(A,B) A
115#define DBUG_SWAP_CODE_STATE(arg) dbug_swap_code_state(arg)
116#define DBUG_FREE_CODE_STATE(arg) dbug_free_code_state(arg)
117#undef DBUG_ASSERT_AS_PRINTF
118
119#ifndef __WIN__
120#define DBUG_ABORT() (_db_flush_(), abort())
121#else
122/*
123 Avoid popup with abort/retry/ignore buttons. When BUG#31745 is fixed we can
124 call abort() instead of _exit(3) (now it would cause a "test signal" popup).
125*/
126#include <crtdbg.h>
127#define DBUG_ABORT() (_db_flush_(),\
128 (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE),\
129 (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR),\
130 _exit(3))
131#endif
132
133/*
134 Make the program fail, without creating a core file.
135 abort() will send SIGABRT which (most likely) generates core.
136 Use SIGKILL instead, which cannot be caught.
137 We also pause the current thread, until the signal is actually delivered.
138 An alternative would be to use _exit(EXIT_FAILURE),
139 but then valgrind would report lots of memory leaks.
140 */
141#ifdef __WIN__
142#define DBUG_SUICIDE() DBUG_ABORT()
143#else
144extern void _db_suicide_(void);
145#define DBUG_SUICIDE() (_db_flush_(), _db_suicide_())
146#endif /* __WIN__ */
147
148#else /* No debugger */
149
150#define DBUG_ENTER(a1)
151#define DBUG_VIOLATION_HELPER_LEAVE do { } while(0)
152#define DBUG_LEAVE
153#define DBUG_RETURN(a1) do { return(a1); } while(0)
154#define DBUG_VOID_RETURN do { return; } while(0)
155#define DBUG_EXECUTE(keyword,a1) do { } while(0)
156#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0)
157#define DBUG_EVALUATE(keyword,a1,a2) (a2)
158#define DBUG_EVALUATE_IF(keyword,a1,a2) (a2)
159#define DBUG_PRINT(keyword,arglist) do { } while(0)
160#define DBUG_PUSH(a1) do { } while(0)
161#define DBUG_SET(a1) do { } while(0)
162#define DBUG_SET_INITIAL(a1) do { } while(0)
163#define DBUG_POP() do { } while(0)
164#define DBUG_PROCESS(a1) do { } while(0)
165#define DBUG_DUMP(keyword,a1,a2) do { } while(0)
166#define DBUG_END() do { } while(0)
167#define DBUG_SLOW_ASSERT(A) do { } while(0)
168#define DBUG_LOCK_FILE do { } while(0)
169#define DBUG_FILE (stderr)
170#define DBUG_UNLOCK_FILE do { } while(0)
171#define DBUG_EXPLAIN(buf,len)
172#define DBUG_EXPLAIN_INITIAL(buf,len)
173#define DEBUGGER_OFF do { } while(0)
174#define DEBUGGER_ON do { } while(0)
175#define IF_DBUG(A,B) B
176#define DBUG_SWAP_CODE_STATE(arg) do { } while(0)
177#define DBUG_FREE_CODE_STATE(arg) do { } while(0)
178#define DBUG_ABORT() do { } while(0)
179#define DBUG_CRASH_ENTER(func)
180#define DBUG_CRASH_RETURN(val) do { return(val); } while(0)
181#define DBUG_CRASH_VOID_RETURN do { return; } while(0)
182#define DBUG_SUICIDE() do { } while(0)
183
184#ifdef DBUG_ASSERT_AS_PRINTF
185extern void (*my_dbug_assert_failed)(const char *assert_expr, const char* file, unsigned long line);
186#define DBUG_ASSERT(assert_expr) do { if (!(assert_expr)) { my_dbug_assert_failed(#assert_expr, __FILE__, __LINE__); }} while (0)
187#define DBUG_ASSERT_EXISTS
188#define IF_DBUG_ASSERT(A,B) A
189#else
190#define DBUG_ASSERT(A) do { } while(0)
191#define IF_DBUG_ASSERT(A,B) B
192#endif /* DBUG_ASSERT_AS_PRINTF */
193#endif /* !defined(DBUG_OFF) && !defined(_lint) */
194
195#ifdef EXTRA_DEBUG
196/**
197 Sync points allow us to force the server to reach a certain line of code
198 and block there until the client tells the server it is ok to go on.
199 The client tells the server to block with SELECT GET_LOCK()
200 and unblocks it with SELECT RELEASE_LOCK(). Used for debugging difficult
201 concurrency problems
202*/
203#define DBUG_SYNC_POINT(lock_name,lock_timeout) \
204 debug_sync_point(lock_name,lock_timeout)
205void debug_sync_point(const char* lock_name, uint lock_timeout);
206#else
207#define DBUG_SYNC_POINT(lock_name,lock_timeout)
208#endif /* EXTRA_DEBUG */
209
210#ifdef __cplusplus
211}
212/*
213 DBUG_LOG() was initially intended for InnoDB. To be able to use it elsewhere
214 one should #include <sstream>. We intentionally avoid including it here to save
215 compilation time.
216*/
217# ifdef DBUG_OFF
218# define DBUG_LOG(keyword, v) do {} while (0)
219# else
220# define DBUG_LOG(keyword, v) do { \
221 if (_db_pargs_(__LINE__, keyword)) { \
222 std::ostringstream _db_s; _db_s << v; \
223 _db_doprnt_("%s", _db_s.str().c_str()); \
224 }} while (0)
225# endif
226#endif
227
228#endif /* _my_dbug_h */
229