The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
debug.h
Go to the documentation of this file.
1#pragma once
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 as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
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
18/** Debugging function definitions and structures
19 *
20 * @file src/lib/util/debug.h
21 *
22 * @copyright 2015-2017 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23 */
24#ifdef __cplusplus
25extern "C" {
26#endif
27
28/*
29 * Default talloc headers have doxygen complaints.
30 */
31#ifdef HAVE_WDOCUMENTATION
32DIAG_OFF(documentation)
33#endif
34#include <talloc.h>
35#ifdef HAVE_WDOCUMENTATION
36DIAG_ON(documentation)
37#endif
38
39#include <freeradius-devel/build.h>
40#include <freeradius-devel/missing.h>
41
42#ifdef NO_ASSERT
43# define MEM(x) error "Use of MEM() not allowed in this source file. Deal with memory allocation failure gracefully"
44#else
45/* Short circuit condition to prevent duplicate evaluation */
46# define MEM(x) do { if (!(x)) { fr_cond_assert_msg(0 && (x), "OUT OF MEMORY"); _fr_exit(__FILE__, __LINE__, EXIT_FAILURE, true); } } while (0)
47#endif
48
49typedef enum {
50 DEBUGGER_STATE_UNKNOWN_NO_PTRACE = -3, //!< We don't have ptrace so can't check.
51 DEBUGGER_STATE_UNKNOWN_NO_PTRACE_CAP = -2, //!< CAP_SYS_PTRACE not set for the process.
52 DEBUGGER_STATE_UNKNOWN = -1, //!< Unknown, likely fr_get_debug_state() not called yet.
53 DEBUGGER_STATE_NOT_ATTACHED = 0, //!< We can attach, so a debugger must not be.
54 DEBUGGER_STATE_ATTACHED = 1 //!< We can't attach, it's likely a debugger is already tracing.
56
57extern int fr_fault_log_fd;
59
60#define FR_FAULT_LOG(_fmt, ...) fr_fault_log(_fmt "\n", ## __VA_ARGS__)
61#define FR_FAULT_LOG_HEX(_data, _data_len) fr_fault_log_hex(_data, _data_len)
62
63/** Optional callback passed to fr_fault_setup
64 *
65 * Allows optional logic to be run before calling the main fault handler.
66 *
67 * If the callback returns < 0, the main fault handler will not be called.
68 *
69 * @param signum signal raised.
70 * @return
71 * - 0 on success.
72 * - < 0 on failure.
73 */
74typedef int (*fr_fault_cb_t)(int signum);
75
76int fr_get_lsan_state(void);
77
78int fr_get_debug_state(void);
79
80void fr_debug_state_store(void);
81
83
84void fr_debug_break(bool always);
85
86void fr_panic_on_free(TALLOC_CTX *ctx);
87
88int fr_set_dumpable_init(void);
89
90int fr_set_dumpable(bool allow_core_dumps);
91
92int fr_reset_dumpable(void);
93
94int fr_log_talloc_report(TALLOC_CTX const *ctx);
95
96void fr_fault(int sig);
97
98void fr_talloc_fault_setup(void);
99
100void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx);
101
102int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program);
103
105
106void fr_fault_set_log_fd(int fd);
107
108void fr_fault_log(char const *msg, ...) CC_HINT(format (printf, 1, 2));
109
110void fr_fault_log_hex(uint8_t const *data, size_t data_len);
111
112/** @name Assertion support functions
113 * @{
114 */
115bool _fr_assert_fail(char const *file, int line, char const *expr, char const *msg, ...)
116 CC_HINT(format (printf, 4, 5));
117
118NEVER_RETURNS void _fr_assert_fatal(char const *file, int line, char const *expr, char const *msg, ...)
119 CC_HINT(format (printf, 4, 5));
120
121NEVER_RETURNS void _fr_exit(char const *file, int line, int status, bool now);
122/** @} */
123
124/** @name Assertion and exit macros
125 * @{
126 */
127
128/** Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x
129 *
130 * Should be wrapped in a condition, and if false, should cause function to return
131 * an error code. This allows control to return to the caller if a precondition is
132 * not satisfied and we're not debugging.
133 *
134 * Example:
135 @verbatim
136 if (!fr_cond_assert(request)) return -1
137 @endverbatim
138 *
139 * @param[in] _x expression to test (should evaluate to true)
140 */
141#define fr_cond_assert(_x) likely((bool)((_x) ? true : (_fr_assert_fail(__FILE__, __LINE__, #_x, NULL) && false)))
142
143/** Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x
144 *
145 * Should be wrapped in a condition, and if false, should cause function to return
146 * an error code. This allows control to return to the caller if a precondition is
147 * not satisfied and we're not debugging.
148 *
149 * Example:
150 @verbatim
151 if (!fr_cond_assert_msg(request, "Bad stuff happened: %s", fr_syserror(errno)))) return -1
152 @endverbatim
153 *
154 * @param[in] _x expression to test (should evaluate to true)
155 * @param[in] _fmt of message to log.
156 * @param[in] ... fmt arguments.
157 */
158#define fr_cond_assert_msg(_x, _fmt, ...) likely((bool)((_x) ? true : (_fr_assert_fail(__FILE__, __LINE__, #_x, _fmt, ## __VA_ARGS__) && false)))
159
160/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
161 *
162 * Example:
163 @verbatim
164 fr_fatal_assert(<extremely_unlikely_and_fatal_condition>);
165 @endverbatim
166 *
167 * @param _x expression to test (should evaluate to true)
168 */
169#define fr_fatal_assert(_x) if (unlikely(!((bool)(_x)))) _fr_assert_fatal(__FILE__, __LINE__, #_x, NULL)
170
171/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
172 *
173 * Should be wrapped in a condition, and if false, should cause function to return
174 * an error code. This allows control to return to the caller if a precondition is
175 * not satisfied and we're not debugging.
176 *
177 * Example:
178 @verbatim
179 fr_fatal_assert(<extremely_unlikely_and_fatal_condition>);
180 @endverbatim
181 *
182 * @param[in] _x expression to test (should evaluate to true)
183 * @param[in] _fmt of message to log.
184 * @param[in] ... fmt arguments.
185 */
186#define fr_fatal_assert_msg(_x, _fmt, ...) if (unlikely(!((bool)(_x)))) _fr_assert_fatal(__FILE__, __LINE__, #_x, _fmt, ## __VA_ARGS__)
187
188/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
189 *
190 * @param[in] _msg to log.
191 * @param[in] ... args.
192 */
193#define fr_fatal_assert_fail(_msg, ...) _fr_assert_fatal(__FILE__, __LINE__, "false", _msg, ## __VA_ARGS__)
194
195#ifdef NDEBUG
196# define fr_assert(_x)
197# define fr_assert_msg(_x, _msg, ...)
198# define fr_assert_fail(_msg, ...)
199#elif !defined(STATIC_ANALYZER)
200/** Calls panic_action ifndef NDEBUG, else logs error
201 *
202 * @param[in] _x expression to test (should evaluate to true)
203 */
204# define fr_assert(_x) if (unlikely(!((bool)(_x)))) _fr_assert_fail(__FILE__, __LINE__, #_x, NULL)
205
206/** Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code 134
207 *
208 * @param[in] _x expression to test (should evaluate to true)
209 * @param[in] _msg to log.
210 * @param[in] ... args.
211 */
212# define fr_assert_msg(_x, _msg, ...) if (unlikely(!((bool)(_x)))) _fr_assert_fail(__FILE__, __LINE__, #_x, _msg, ## __VA_ARGS__)
213/** Calls panic_action ifndef NDEBUG, else logs error
214 *
215 * @param[in] _msg to log.
216 * @param[in] ... args.
217 */
218#define fr_assert_fail(_msg, ...) _fr_assert_fail(__FILE__, __LINE__, "false", _msg, ## __VA_ARGS__)
219#else
220# include <assert.h>
221# define fr_assert(_x) assert(_x)
222# define fr_assert_msg(_x, _msg, ...) assert(_x)
223# define fr_assert_fail(_msg ...) assert(0)
224#endif
225
226/** Exit, producing a log message in debug builds
227 *
228 * @param[in] _x code to exit with.
229 */
230# define fr_exit(_x) _fr_exit(__FILE__, __LINE__, (_x), false)
231
232/** Exit without calling atexit() handlers, producing a log message in debug builds
233 *
234 * @param[in] _x code to exit with.
235 */
236# define fr_exit_now(_x) _fr_exit(__FILE__, __LINE__, (_x), true)
237/** @} */
238
239#ifdef __cplusplus
240}
241#endif
int const char * file
Definition acutest.h:702
log_entry msg
Definition acutest.h:794
int const char int line
Definition acutest.h:702
#define NEVER_RETURNS
Should be placed before the function return type.
Definition build.h:334
#define DIAG_ON(_x)
Definition build.h:481
#define DIAG_OFF(_x)
Definition build.h:480
char const * fr_debug_state_to_msg(fr_debug_state_t state)
Return current value of debug_state.
Definition debug.c:512
bool _fr_assert_fail(char const *file, int line, char const *expr, char const *msg,...))
A soft assertion which triggers the fault handler in debug builds.
Definition debug.c:1247
fr_debug_state_t
Definition debug.h:49
@ DEBUGGER_STATE_NOT_ATTACHED
We can attach, so a debugger must not be.
Definition debug.h:53
@ DEBUGGER_STATE_UNKNOWN_NO_PTRACE
We don't have ptrace so can't check.
Definition debug.h:50
@ DEBUGGER_STATE_UNKNOWN_NO_PTRACE_CAP
CAP_SYS_PTRACE not set for the process.
Definition debug.h:51
@ DEBUGGER_STATE_UNKNOWN
Unknown, likely fr_get_debug_state() not called yet.
Definition debug.h:52
@ DEBUGGER_STATE_ATTACHED
We can't attach, it's likely a debugger is already tracing.
Definition debug.h:54
void fr_disable_null_tracking_on_free(TALLOC_CTX *ctx)
Disable the null tracking context when a talloc chunk is freed.
Definition debug.c:1021
void fr_fault_set_log_fd(int fd)
Set a file descriptor to log memory reports to.
Definition debug.c:1233
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition debug.c:962
int fr_set_dumpable(bool allow_core_dumps)
Enable or disable core dumps.
Definition debug.c:675
void fr_fault_log(char const *msg,...))
Log output to the fr_fault_log_fd.
Definition debug.c:1199
int fr_fault_log_fd
Where to write debug output.
Definition debug.c:72
int(* fr_fault_cb_t)(int signum)
Optional callback passed to fr_fault_setup.
Definition debug.h:74
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
Definition debug.c:743
int fr_fault_setup(TALLOC_CTX *ctx, char const *cmd, char const *program)
Registers signal handlers to execute panic_action on fatal signal.
Definition debug.c:1056
NEVER_RETURNS void _fr_assert_fatal(char const *file, int line, char const *expr, char const *msg,...))
A fatal assertion which triggers the fault handler in debug builds or exits.
Definition debug.c:1283
int fr_get_lsan_state(void)
Definition debug.c:232
void fr_debug_state_store(void)
Should be run before using setuid or setgid to get useful results.
Definition debug.c:492
void fr_fault(int sig)
Prints a simple backtrace (if execinfo is available) and calls panic_action if set.
Definition debug.c:799
NEVER_RETURNS void _fr_exit(char const *file, int line, int status, bool now)
Exit possibly printing a message about why we're exiting.
Definition debug.c:1315
void fr_talloc_fault_setup(void)
Register talloc fault handlers.
Definition debug.c:1037
void fr_debug_break(bool always)
Break in debugger (if were running under a debugger)
Definition debug.c:541
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition debug.c:1185
void fr_fault_log_hex(uint8_t const *data, size_t data_len)
Print data as a hex block.
Definition debug.c:1213
int fr_set_dumpable_init(void)
Get the current maximum for core files.
Definition debug.c:660
void fr_panic_on_free(TALLOC_CTX *ctx)
Insert memory into the context of another talloc memory chunk which causes a panic when freed.
Definition debug.c:565
fr_debug_state_t fr_debug_state
Whether we're attached to by a debugger.
Definition debug.c:74
int fr_get_debug_state(void)
Definition debug.c:480
unsigned char uint8_t
static char const * program
Definition radiusd.c:79
Functions which we wish were included in the standard talloc distribution.
static fr_slen_t data
Definition value.h:1340