master
h 94 lines 4.29 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_DICTIONARY_DEBUG_H
4 #define NETDATA_DICTIONARY_DEBUG_H
5
6 #include "dictionary.h"
7
8 #ifdef FSANITIZE_ADDRESS
9
10 // Initialize dictionary debugging
11 void dictionary_debug_init(void);
12
13 // Register a dictionary for tracking (when FSANITIZE_ADDRESS is defined)
14 void dictionary_debug_track_dict(DICTIONARY *dict);
15
16 // Unregister a dictionary from tracking
17 void dictionary_debug_untrack_dict(DICTIONARY *dict);
18
19 // Print information about dictionaries that are still allocated
20 void dictionary_print_still_allocated_stacktraces(void);
21
22 // Print information about dictionaries that have delayed destruction due to referenced items
23 void dictionary_debug_print_delayed_dictionaries(size_t destroyed_dicts);
24
25 // Clean up resources used for tracking
26 void dictionary_debug_shutdown(void);
27
28 void dictionary_debug_internal_check_with_trace(DICTIONARY *dict, DICTIONARY_ITEM *item, const char *function, bool allow_null_dict, bool allow_null_item);
29 #define dictionary_debug_internal_check(dict, item, allow_null_dict, allow_null_item) \
30 dictionary_debug_internal_check_with_trace(dict, item, __FUNCTION__, allow_null_dict, allow_null_item)
31
32 // For internal_error with dictionary stacktrace
33 #define dictionary_internal_error(condition, dict, fmt, args...) do { \
34 if(unlikely(condition)) { \
35 BUFFER *__wb = buffer_create(1024, NULL); \
36 if ((dict) && ((dict)->stacktraces.num_stacktraces > 0)) { \
37 buffer_sprintf(__wb, fmt " Dictionary accessed at:\n", ##args); \
38 for (int i = 0; i < (dict)->stacktraces.num_stacktraces && i < 3; i++) { \
39 if ((dict)->stacktraces.stacktraces[i]) { \
40 buffer_sprintf(__wb, "Stacktrace #%d:\n", i+1); \
41 stacktrace_to_buffer((dict)->stacktraces.stacktraces[i], __wb); \
42 buffer_strcat(__wb, "\n"); \
43 } \
44 } \
45 if ((dict)->stacktraces.num_stacktraces > 3) \
46 buffer_sprintf(__wb, "...and %d more stacktraces\n", (dict)->stacktraces.num_stacktraces - 3); \
47 } else { \
48 buffer_sprintf(__wb, fmt " Dictionary stacktrace not available", ##args); \
49 } \
50 netdata_logger(NDLS_DAEMON, NDLP_DEBUG, __FILE__, __FUNCTION__, __LINE__, "BEGIN --\n%s\n-- END", buffer_tostring(__wb)); \
51 buffer_free(__wb); \
52 } \
53 } while(0)
54
55 // For internal_fatal with dictionary stacktrace
56 #define dictionary_internal_fatal(condition, dict, fmt, args...) do { \
57 if(unlikely(condition)) { \
58 BUFFER *__wb = buffer_create(1024, NULL); \
59 if ((dict) && ((dict)->stacktraces.num_stacktraces > 0)) { \
60 buffer_sprintf(__wb, fmt " Dictionary accessed at:\n", ##args); \
61 for (int i = 0; i < (dict)->stacktraces.num_stacktraces && i < 3; i++) { \
62 if ((dict)->stacktraces.stacktraces[i]) { \
63 buffer_sprintf(__wb, "Stacktrace #%d:\n", i+1); \
64 stacktrace_to_buffer((dict)->stacktraces.stacktraces[i], __wb); \
65 buffer_strcat(__wb, "\n"); \
66 } \
67 } \
68 if ((dict)->stacktraces.num_stacktraces > 3) \
69 buffer_sprintf(__wb, "...and %d more stacktraces\n", (dict)->stacktraces.num_stacktraces - 3); \
70 } else { \
71 buffer_sprintf(__wb, fmt " Dictionary stacktrace not available", ##args); \
72 } \
73 netdata_logger_fatal(__FILE__, __FUNCTION__, __LINE__, "BEGIN --\n%s\n--END", buffer_tostring(__wb)); \
74 buffer_free(__wb); \
75 } \
76 } while(0)
77
78 #else
79
80 #define dictionary_debug_init(void) debug_dummy()
81 #define dictionary_debug_track_dict(dict) debug_dummy()
82 #define dictionary_debug_untrack_dict(dict) debug_dummy()
83 #define dictionary_print_still_allocated_stacktraces(void) debug_dummy()
84 #define dictionary_debug_print_delayed_dictionaries(destroyed_dicts) debug_dummy()
85 #define dictionary_debug_shutdown(void) debug_dummy()
86
87 #define dictionary_debug_internal_check(dict, item, allow_null_dict, allow_null_item) debug_dummy()
88 #define dictionary_debug_internal_check_with_trace(dict, item, function, allow_null_dict, allow_null_item) debug_dummy()
89
90 #define dictionary_internal_error(condition, dict, fmt, args...) debug_dummy()
91 #define dictionary_internal_fatal(condition, dict, fmt, args...) debug_dummy()
92 #endif
93
94 #endif // NETDATA_DICTIONARY_DEBUG_H