MySQL 8.3.0
Source Code Documentation
my_dbug.h
Go to the documentation of this file.
1/* Copyright (c) 2000, 2023, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23#ifndef MY_DBUG_INCLUDED
24#define MY_DBUG_INCLUDED
25
26/**
27 @file include/my_dbug.h
28*/
29
30#ifdef MY_MSCRT_DEBUG
31#include <crtdbg.h>
32#endif
33#include <stdlib.h>
34
35#include "my_compiler.h"
36
37#include <string.h>
38
39#if !defined(NDEBUG)
40#include <assert.h> // IWYU pragma: keep
41#include <stdio.h>
42#endif
43
44/**
45 Calls our own implementation of abort, if specified, or std's abort().
46 */
47[[noreturn]] void my_abort();
48/**
49 Sets a new function to be called on my_abort().
50
51 @param new_my_abort_func pointer to a new my_abort function. It can't be
52 [[noreturn]] as pointers to methods can't have attributes.
53 */
54void set_my_abort(void (*new_my_abort_func)());
55
56#if !defined(NDEBUG)
57
59 const char *func; /* function name of the previous stack frame */
60 int func_len; /* how much to print from func */
61 const char *file; /* filename of the function of previous frame */
62 unsigned int level; /* this nesting level, highest bit enables tracing */
63 struct _db_stack_frame_ *prev; /* pointer to the previous frame */
64};
65
66struct CODE_STATE;
67
68extern int _db_keyword_(struct CODE_STATE *, const char *, int);
69extern int _db_explain_(struct CODE_STATE *cs, char *buf, size_t len);
70extern int _db_explain_init_(char *buf, size_t len);
71extern int _db_is_pushed_(void);
72extern void _db_process_(const char *name);
73extern void _db_push_(const char *control);
74extern void _db_pop_(void);
75extern void _db_set_(const char *control);
76extern void _db_set_init_(const char *control);
77extern void _db_enter_(const char *_func_, int func_len, const char *_file_,
78 unsigned int _line_,
79 struct _db_stack_frame_ *_stack_frame_);
80extern void _db_return_(unsigned int _line_,
81 struct _db_stack_frame_ *_stack_frame_);
82extern void _db_pargs_(unsigned int _line_, const char *keyword);
83extern int _db_enabled_();
84extern void _db_doprnt_(const char *format, ...)
85 MY_ATTRIBUTE((format(printf, 1, 2)));
86extern void _db_dump_(unsigned int _line_, const char *keyword,
87 const unsigned char *memory, size_t length);
88extern void _db_end_(void);
89extern void _db_lock_file_(void);
90extern void _db_unlock_file_(void);
91extern FILE *_db_fp_(void);
92extern void _db_flush_();
93
94#ifdef __cplusplus
95
96#if defined(__GNUC__)
97// GCC, Clang, and compatible compilers.
98#define DBUG_PRETTY_FUNCTION __PRETTY_FUNCTION__
99#elif defined(__FUNCSIG__)
100// For MSVC; skips the __cdecl. (__PRETTY_FUNCTION__ in GCC is not a
101// preprocessor constant, but __FUNCSIG__ in MSVC is.)
102#define DBUG_PRETTY_FUNCTION strchr(__FUNCSIG__, ' ') + 1
103#else
104// Standard C++; does not include the class name.
105#define DBUG_PRETTY_FUNCTION __func__
106#endif
107
108/**
109 A RAII helper to do DBUG_ENTER / DBUG_RETURN for you automatically. Use like
110 this:
111
112 int foo() {
113 DBUG_TRACE;
114 return 42;
115 }
116 */
118 public:
119 AutoDebugTrace(const char *function, const char *filename, int line) {
120 // Remove the return type, if it's there.
121 const char *begin = strchr(function, ' ');
122 if (begin != nullptr) {
123 function = begin + 1;
124 }
125
126 // Cut it off at the first parenthesis; the argument list is
127 // often too long to be interesting.
128 const char *end = strchr(function, '(');
129
130 if (end == nullptr) {
131 _db_enter_(function, static_cast<int>(strlen(function)), filename, line,
133 } else {
134 _db_enter_(function, static_cast<int>(end - function), filename, line,
136 }
137 }
138
140
141 private:
143};
144
145#define DBUG_TRACE \
146 const AutoDebugTrace _db_trace(DBUG_PRETTY_FUNCTION, __FILE__, __LINE__)
147
148#endif
149
150#define DBUG_ENTER(a) \
151 struct _db_stack_frame_ _db_stack_frame_; \
152 _db_enter_(a, ::strlen(a), __FILE__, __LINE__, &_db_stack_frame_)
153
154#define DBUG_RETURN(a1) \
155 do { \
156 _db_return_(__LINE__, &_db_stack_frame_); \
157 return (a1); \
158 } while (0)
159#define DBUG_VOID_RETURN \
160 do { \
161 _db_return_(__LINE__, &_db_stack_frame_); \
162 return; \
163 } while (0)
164#define DBUG_EXECUTE(keyword, a1) \
165 do { \
166 if (_db_keyword_(nullptr, (keyword), 0)) { \
167 a1 \
168 } \
169 } while (0)
170#define DBUG_EXECUTE_IF(keyword, a1) \
171 do { \
172 if (_db_keyword_(nullptr, (keyword), 1)) { \
173 a1 \
174 } \
175 } while (0)
176#define DBUG_EVALUATE(keyword, a1, a2) \
177 (_db_keyword_(nullptr, (keyword), 0) ? (a1) : (a2))
178#define DBUG_EVALUATE_IF(keyword, a1, a2) \
179 (_db_keyword_(nullptr, (keyword), 1) ? (a1) : (a2))
180#define DBUG_PRINT(keyword, arglist) \
181 do { \
182 _db_pargs_(__LINE__, keyword); \
183 if (_db_enabled_()) { \
184 _db_doprnt_ arglist; \
185 } \
186 } while (0)
187
188#define DBUG_PUSH(a1) _db_push_(a1)
189#define DBUG_POP() _db_pop_()
190#define DBUG_SET(a1) _db_set_(a1)
191#define DBUG_SET_INITIAL(a1) _db_set_init_(a1)
192#define DBUG_PROCESS(a1) _db_process_(a1)
193#define DBUG_FILE _db_fp_()
194#define DBUG_DUMP(keyword, a1, a2) _db_dump_(__LINE__, keyword, a1, a2)
195#define DBUG_END() _db_end_()
196#define DBUG_LOCK_FILE _db_lock_file_()
197#define DBUG_UNLOCK_FILE _db_unlock_file_()
198#define DBUG_EXPLAIN(buf, len) _db_explain_(nullptr, (buf), (len))
199#define DBUG_EXPLAIN_INITIAL(buf, len) _db_explain_init_((buf), (len))
200#ifndef _WIN32
201#define DBUG_ABORT() (_db_flush_(), my_abort())
202#define DBUG_EXIT() (_db_flush_(), exit(2))
203#else
204#include <crtdbg.h>
205
206#define DBUG_ABORT() \
207 (_db_flush_(), (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE), \
208 (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR), my_abort())
209#define DBUG_EXIT() \
210 (_db_flush_(), (void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE), \
211 (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR), _exit(2))
212#endif
213
214/*
215 Make the program fail, without creating a core file.
216 abort() will send SIGABRT which (most likely) generates core.
217 Use SIGKILL instead, which cannot be caught.
218 We also pause the current thread, until the signal is actually delivered.
219 An alternative would be to use _exit(EXIT_FAILURE),
220 but then valgrind would report lots of memory leaks.
221 */
222#ifdef _WIN32
223#define DBUG_SUICIDE() DBUG_EXIT()
224#else
225[[noreturn]] extern void _db_suicide_();
226extern void _db_flush_gcov_();
227#define DBUG_SUICIDE() (_db_flush_(), _db_suicide_())
228#endif
229
230#else /* No debugger */
231
232#ifdef __cplusplus
233#define DBUG_TRACE \
234 do { \
235 } while (false)
236#endif
237#define DBUG_ENTER(a1)
238#define DBUG_RETURN(a1) \
239 do { \
240 return (a1); \
241 } while (0)
242#define DBUG_VOID_RETURN \
243 do { \
244 return; \
245 } while (0)
246#define DBUG_EXECUTE(keyword, a1) \
247 do { \
248 } while (0)
249#define DBUG_EXECUTE_IF(keyword, a1) \
250 do { \
251 } while (0)
252#define DBUG_EVALUATE(keyword, a1, a2) (a2)
253#define DBUG_EVALUATE_IF(keyword, a1, a2) (a2)
254#define DBUG_PRINT(keyword, arglist) \
255 do { \
256 } while (0)
257#define DBUG_PUSH(a1) \
258 do { \
259 } while (0)
260#define DBUG_SET(a1) \
261 do { \
262 } while (0)
263#define DBUG_SET_INITIAL(a1) \
264 do { \
265 } while (0)
266#define DBUG_POP() \
267 do { \
268 } while (0)
269#define DBUG_PROCESS(a1) \
270 do { \
271 } while (0)
272#define DBUG_DUMP(keyword, a1, a2) \
273 do { \
274 } while (0)
275#define DBUG_END() \
276 do { \
277 } while (0)
278#define DBUG_LOCK_FILE \
279 do { \
280 } while (0)
281#define DBUG_FILE (stderr)
282#define DBUG_UNLOCK_FILE \
283 do { \
284 } while (0)
285#define DBUG_EXPLAIN(buf, len)
286#define DBUG_EXPLAIN_INITIAL(buf, len)
287#define DBUG_ABORT() \
288 do { \
289 } while (0)
290#define DBUG_SUICIDE() \
291 do { \
292 } while (0)
293
294#endif
295
296#ifdef __cplusplus
297#if !defined(NDEBUG)
298#include <sstream>
299#include <string>
300
301/*
302 A C++ interface to the DBUG_PRINT macro. The DBUG_LOG macro takes two
303 arguments. The first argument is the keyword, as that of the
304 DBUG_PRINT. The 2nd argument 'v' will be passed to a C++ output stream.
305 This enables the use of C++ style output stream operator. In the code, it
306 will be used as follows:
307
308 DBUG_LOG("blob", "space: " << space_id);
309
310 Note: DBUG_PRINT() has a limitation of 1024 bytes for a single
311 print out. So, this limitation is there for DBUG_LOG macro also.
312*/
313
314#define DBUG_LOG(keyword, v) \
315 do { \
316 _db_pargs_(__LINE__, keyword); \
317 if (_db_enabled_()) { \
318 std::ostringstream sout; \
319 sout << v; \
320 DBUG_PRINT(keyword, ("%s", sout.str().c_str())); \
321 } \
322 } while (0)
323
324/**
325 Shortcut for printing a variable name and its value in DBUG_LOG output.
326
327 Use like:
328
329 DBUG_LOG("info", DBUG_VAR(i) << " " << DBUG_VAR(thd->query));
330
331 Example output for the above might be:
332
333 i=[4711] thd->query=[INSERT INTO t VALUES (1)]
334*/
335#define DBUG_VAR(v) #v << "=[" << (v) << "]"
336
337#else /* NDEBUG */
338#define DBUG_LOG(keyword, v) \
339 do { \
340 } while (0)
341#define DBUG_VAR(v) ""
342#endif /* NDEBUG */
343
344/**
345 A type-safe interface to DBUG_EXECUTE_IF, where the debug action to
346 activate when the keyword is provided is given as a callable object
347 (typically a lambda).
348
349 @note The body of the callable will be checked by the compiler even
350 in optimized mode.
351
352 @param keyword String literal which will enable this debug action.
353 @param clos Callable object taking no arguments which will be
354 called in debug mode if the keyword is enabled.
355 */
356template <class DBGCLOS>
357inline void dbug(const char *keyword [[maybe_unused]],
358 DBGCLOS &&clos [[maybe_unused]]) {
359 DBUG_EXECUTE_IF(keyword, clos(););
360}
361
362#endif /* __cplusplus */
363#endif /* MY_DBUG_INCLUDED */
A RAII helper to do DBUG_ENTER / DBUG_RETURN for you automatically.
Definition: my_dbug.h:117
AutoDebugTrace(const char *function, const char *filename, int line)
Definition: my_dbug.h:119
~AutoDebugTrace()
Definition: my_dbug.h:139
_db_stack_frame_ m_stack_frame
Definition: my_dbug.h:142
Header for compiler-dependent features.
void _db_dump_(unsigned int _line_, const char *keyword, const unsigned char *memory, size_t length)
int _db_keyword_(struct CODE_STATE *, const char *, int)
Definition: dbug.cc:1761
void _db_lock_file_(void)
Definition: dbug.cc:2176
void _db_return_(unsigned int _line_, struct _db_stack_frame_ *_stack_frame_)
void _db_flush_()
Definition: dbug.cc:2126
#define DBUG_EXECUTE_IF(keyword, a1)
Definition: my_dbug.h:170
void _db_unlock_file_(void)
Definition: dbug.cc:2183
void my_abort()
Calls our own implementation of abort, if specified, or std's abort().
Definition: my_init.cc:260
void _db_set_(const char *control)
Definition: dbug.cc:803
void _db_pop_(void)
Definition: dbug.cc:907
void _db_end_(void)
Definition: dbug.cc:1663
void _db_set_init_(const char *control)
Definition: dbug.cc:882
void _db_suicide_()
Definition: dbug.cc:2153
void _db_doprnt_(const char *format,...)
Definition: dbug.cc:1314
void _db_flush_gcov_()
Definition: dbug.cc:2144
void _db_enter_(const char *_func_, int func_len, const char *_file_, unsigned int _line_, struct _db_stack_frame_ *_stack_frame_)
void _db_process_(const char *name)
Definition: dbug.cc:400
FILE * _db_fp_(void)
Definition: dbug.cc:1735
void dbug(const char *keyword, DBGCLOS &&clos)
A type-safe interface to DBUG_EXECUTE_IF, where the debug action to activate when the keyword is prov...
Definition: my_dbug.h:357
int _db_explain_init_(char *buf, size_t len)
Definition: dbug.cc:1081
void _db_push_(const char *control)
Definition: dbug.cc:839
int _db_explain_(struct CODE_STATE *cs, char *buf, size_t len)
Definition: dbug.cc:1021
void _db_pargs_(unsigned int _line_, const char *keyword)
void set_my_abort(void(*new_my_abort_func)())
Sets a new function to be called on my_abort().
Definition: my_init.cc:269
int _db_enabled_()
Definition: dbug.cc:1278
int _db_is_pushed_(void)
Returns true if session-local settings have been set.
Definition: dbug.cc:861
void * begin(THD *thd, const TABLE *table, size_t data_size, size_t memory, size_t num_threads) noexcept
Definition: bulk_data_service.cc:1533
Definition: buf0block_hint.cc:29
const std::string FILE("FILE")
Definition: commit_order_queue.h:33
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:75
Definition: aligned_atomic.h:43
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:191
const char * filename
Definition: pfs_example_component_population.cc:66
case opt name
Definition: sslopt-case.h:32
Definition: dbug.cc:220
int func_len
Definition: dbug.cc:223
Definition: my_dbug.h:58
struct _db_stack_frame_ * prev
Definition: my_dbug.h:63
const char * func
Definition: my_dbug.h:59
int func_len
Definition: my_dbug.h:60
unsigned int level
Definition: my_dbug.h:62
const char * file
Definition: my_dbug.h:61