2 This file is part of the NoBug debugging library.
5 2006, 2007, 2008, 2009, Christian Thaeter <ct@pipapo.org>
6 2010, Christian Thaeter <ct@pipapo.org>
7 2009, Francois Kubler <ih8tehuman@free.fr>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
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 for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
25 #ifndef NOBUG_LIBNOBUG_C /* not when building libnobug */
28 #error NDEBUG incompatible with -DEBUG_ALPHA
31 #error NDEBUG incompatible with -DEBUG_BETA
35 #if defined(EBUG_ALPHA)
36 # define NOBUG_MODE_ALPHA 1
37 # define NOBUG_MODE_BETA 0
38 # define NOBUG_MODE_RELEASE 0
39 #elif defined(EBUG_BETA)
40 # define NOBUG_MODE_ALPHA 0
41 # define NOBUG_MODE_BETA 1
42 # define NOBUG_MODE_RELEASE 0
44 # define NOBUG_MODE_ALPHA 0
45 # define NOBUG_MODE_BETA 0
46 # define NOBUG_MODE_RELEASE 1
48 #error no debug level and no NDEBUG defined
50 #endif /* NOBUG_LIBNOBUG_C */
63 #ifdef HAVE_EXECINFO_H
64 # ifndef NOBUG_USE_EXECINFO
65 # define NOBUG_USE_EXECINFO 1
68 # undef NOBUG_USE_EXECINFO
69 # define NOBUG_USE_EXECINFO 0
72 #if NOBUG_USE_EXECINFO
76 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
77 # ifndef NOBUG_USE_VALGRIND
78 # define NOBUG_USE_VALGRIND 1
81 # undef NOBUG_USE_VALGRIND
82 # define NOBUG_USE_VALGRIND 0
85 #if NOBUG_USE_VALGRIND
90 # ifndef NOBUG_USE_PTHREAD
91 # define NOBUG_USE_PTHREAD 1
94 # ifdef NOBUG_USE_PTHREAD
95 # undef NOBUG_USE_PTHREAD
97 # define NOBUG_USE_PTHREAD 0
100 #if NOBUG_USE_PTHREAD
106 figure out how to find out the current function name, this is compiler and language dependent
108 #if !defined(NOBUG_FUNC) && defined(__STDC_VERSION__)
109 /* C99 defines __func__ */
110 # if __STDC_VERSION__ >= 199901L
111 # define NOBUG_FUNC __func__
115 #if !defined(NOBUG_FUNC) && defined(__GNUC__)
116 /* the gnu compiler (since 2.x) defines __FUNCTION__ */
118 # define NOBUG_FUNC __FUNCTION__
122 #if !defined(NOBUG_FUNC) && defined(__SUNPRO_C)
123 /* the sun C compiler defines __FUNCTION__, the version is determined by a sochastic test, please report! */
124 # if __SUNPRO_C >= 0x5100
125 # define NOBUG_FUNC __FUNCTION__
129 /* add more heuristics here... */
132 /* generic fallback, check for some common definitions (its not guranteed that this symbols are preprocessor defines), just some guesswork */
135 # define NOBUG_FUNC __func__
136 # elif defined(__FUNCTION__)
137 # define NOBUG_FUNC __FUNCTION__
139 /* finally a fallback when nothing found */
140 # define NOBUG_FUNC "-"
146 //assertions HEAD- Macros for Assertions; assertions; assert the state of the application
148 //assertions The assertion set of macros provide a convenient status check on whether
149 //assertions to continue running, or abort execution as some condition was not fulfilled.
150 //assertions Assertion failures are fatal and must abort the application immediately by
151 //assertions calling the xref:ABORT[NOBUG_ABORT] macro which in turn may call a user defined
152 //assertions xref:abortcallback[abort hook].
154 //assertions PARA CHECK; CHECK; unnconditional assertion for test suites
156 //assertions CHECK(expr, ...)
157 //assertions CHECK_IF(when, expr, ...)
159 //assertions This assertion is never optimized out. Its main purpose is in implementing
160 //assertions test suites where one would like to assert tests independent of the build level.
163 #define NOBUG_CHECK(expr, ...) \
164 NOBUG_ASSERT_(expr, "CHECK", NOBUG_CONTEXT, ""__VA_ARGS__)
166 #define NOBUG_CHECK_IF(when, expr, ...) \
167 NOBUG_WHEN(when, NOBUG_CHECK(expr, ""__VA_ARGS__))
171 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
173 //assertions REQUIRE(expr, ...)
174 //assertions REQUIRE_IF(when, expr, ...)
175 //assertions NOBUG_REQUIRE_CTX(expr, context,...)
176 //assertions NOBUG_REQUIRE_IF_CTX(when, expr, context, ...)
178 //assertions Precondition (input) check. Use these macros to validate the input a
179 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds,
180 //assertions but have not effect in *RELEASE* builds.
183 #define NOBUG_REQUIRE(expr, ...) \
184 NOBUG_REQUIRE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
186 #define NOBUG_REQUIRE_CTX(expr, context, ...) \
187 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", context, ""__VA_ARGS__))
190 #define NOBUG_REQUIRE_IF(when, expr, context,...) \
191 NOBUG_REQUIRE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
193 #define NOBUG_REQUIRE_IF_CTX(when, expr, context,...) \
194 NOBUG_IF_NOT_RELEASE ( \
195 NOBUG_WHEN(when, NOBUG_REQUIRE_CTX(expr, context, ""__VA_ARGS__)) \
200 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
202 //assertions ENSURE(expr, ...)
203 //assertions ENSURE_IF(when, expr, ...)
204 //assertions NOBUG_ENSURE_CTX(expr, context, ...)
205 //assertions NOBUG_ENSURE_IF_CTX(when, expr, context, ...)
207 //assertions Postcondition (progress/output) check. Use these macros to validate the
208 //assertions data a function produces (example: return value). `ENSURE` is enabled
209 //assertions unconditionally in *ALPHA* builds and have no effect in *BETA* builds for
210 //assertions scopes which are tagged as `CHECKED`.
212 //assertions The `ENSURE_IF` variants are enabled in *ALPHA* and *BETA* builds.
214 //assertions In *RELEASE* builds these checks are optimized out.
217 #define NOBUG_ENSURE(expr, ...) \
218 NOBUG_ENSURE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
220 #define NOBUG_ENSURE_CTX(expr, context, ...) \
221 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
222 context, ""__VA_ARGS__)) \
224 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
225 NOBUG_ASSERT_(expr, "POSTCONDITION", \
226 context, ""__VA_ARGS__) \
231 #define NOBUG_ENSURE_IF(when, expr, ...) \
232 NOBUG_ENSURE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
234 #define NOBUG_ENSURE_IF_CTX(when, expr, context, ...) \
235 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE_CTX(expr, context, ""__VA_ARGS__)))
239 //assertions PARA ASSERT; ASSERT; generic assertion
241 //assertions ASSERT(expr, ...)
242 //assertions ASSERT_IF(when, expr, ...)
243 //assertions NOBUG_ASSERT_CTX(expr, context, ...)
244 //assertions NOBUG_ASSERT_IF_CTX(when, expr, context, ...)
246 //assertions Generic check. Use these macros when you want to validate something
247 //assertions which doesn't fall into one of the above categories. Generally to be
248 //assertions avoided! The checks are enabled in *ALPHA* and *BETA* builds and
249 //assertions have no effect in *RELEASE* builds.
252 #define NOBUG_ASSERT(expr, ...) \
253 NOBUG_ASSERT_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
255 #define NOBUG_ASSERT_CTX(expr, context, ...) \
256 NOBUG_IF_NOT_RELEASE( \
257 NOBUG_ASSERT_(expr, "ASSERTION", \
258 context, ""__VA_ARGS__) \
262 #define NOBUG_ASSERT_IF(when, expr, ...) \
263 NOBUG_ASSERT_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
265 #define NOBUG_ASSERT_IF_CTX(when, expr, context, ...) \
266 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_CTX(expr, context, ""__VA_ARGS__)))
270 //assertions PARA assert; assert; C standard assertion
272 //assertions assert(expr)
274 //assertions NoBug overrides the standard `assert` macro, using `NOBUG_ASSERT`.
275 //assertions This is just a compatibility feature, its use is not suggested.
279 #define assert(expr) NOBUG_ASSERT(expr)
286 #define NOBUG_ASSERT_(expr, what, context, fmt, ...) \
287 NOBUG_WHEN (!(expr), \
288 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
289 what, context, "(%s) " fmt, \
290 #expr, ## __VA_ARGS__); \
291 NOBUG_BACKTRACE_CTX(context); \
294 #else /* , ## __VA_ARGS__ eating the comma when the arglist is empty is a gcc extension, fallback for other compilers */
295 #define NOBUG_ASSERT_(expr, what, context, ...) \
296 NOBUG_WHEN (!(expr), \
297 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
300 NOBUG_BACKTRACE_CTX(context); \
306 //assertions PARA INVARIANT; INVARIANT; validate invariant state
308 //assertions INVARIANT(type, pointer, depth)
309 //assertions INVARIANT_IF(when,type, pointer, depth)
310 //assertions INVARIANT_ASSERT(expr, ...)
312 //assertions Checking invariants. You can provide more complex checking functions
313 //assertions which test the validity of datastructures. Invariants are only enabled
314 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
315 //assertions otherwise optimized out.
317 //assertions TODO: describe how to create invariant checks
319 // 'invariant_context' must be passed in
321 #define NOBUG_INVARIANT(type, pointer, depth, extra) \
323 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
324 NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth, \
325 NOBUG_CONTEXT, extra) \
330 #define NOBUG_INVARIANT_IF(when, type, pointer, depth, extra) \
332 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
334 NOBUG_CAT3(nobug_, type,_invariant)(pointer, depth, \
340 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
341 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__)
343 #define NOBUG_INVARIANT_ASSERT_IF(when, expr, ...) \
345 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__) \
349 checked/unchecked tagged scopes
351 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
353 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
355 #define NOBUG_UNCHECKED \
356 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
357 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
361 /*TODO dump-level for flags instead limits[0]*/
363 //dumpmacros PARA DUMP; DUMP; dumping datastructures
365 //dumpmacros DUMP(flag, type, pointer, depth, extra)
366 //dumpmacros DUMP_IF(when, flag, type, pointer, depth, extra)
368 //dumpmacros These macros call a data structure dump of the object (`pointer`) in question.
369 //dumpmacros `DUMP` has only effect in *ALPHA* and *BETA* builds, `DUMP_IF` is also
370 //dumpmacros enabled for RELEASE builds.
372 //dumpmacros `extra` is a void* which is transparently passed around and can be used to
373 //dumpmacros pass a particular state around. NoBug does not alter this.
376 #define NOBUG_DUMP(flag, type, pointer, depth, extra) \
377 NOBUG_IF_NOT_RELEASE( \
378 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
379 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra) \
383 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth, extra) \
384 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET] && when, \
385 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT, extra) \
390 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
392 //dumpmacros DUMP_LOG(...)
393 //dumpmacros DUMP_LOG_IF(when, ...)
395 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
398 #define NOBUG_DUMP_LOG(...) \
399 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
400 "DUMP", dump_context, \
403 #define NOBUG_DUMP_LOG_IF(expr, ...) \
405 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
406 "DUMP", dump_context, \
412 //dumpmacros PARA DUMP_LEVEL; DUMP_LEVEL; logging level at which DUMPs are done
414 //dumpmacros #define NOBUG_DUMP_LEVEL ...
416 //dumpmacros Dumping is by default done at `LOG_DEBUG` level, this can be overridden by
417 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other logging level.
420 #ifndef NOBUG_DUMP_LEVEL
421 #define NOBUG_DUMP_LEVEL LOG_DEBUG
426 //logmacros HEAD- Macros That Log Information; logging; generate logging messages
428 //logmacros Logging targets a flag (except for `ECHO`) and is done at a log-level related to syslog levels.
430 //logmacros PARA ECHO; ECHO; unconditional logging for tests
432 //logmacros ECHO(...)
434 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
435 //logmacros testsuites where one would like to print and log messages independent of the build level
438 #define NOBUG_ECHO(...) \
439 NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, "ECHO", NOBUG_CONTEXT, ""__VA_ARGS__)
443 //logmacros PARA ALERT; ALERT; about to die
445 //logmacros ALERT(flag, ...)
446 //logmacros ALERT_IF(when, flag, ...)
447 //logmacros NOBUG_ALERT_CTX(flag, context, ...)
448 //logmacros NOBUG_ALERT_IF_CTX(when, flag, context, ...)
450 //logmacros This is the most critical condition that might be registered by
451 //logmacros an application. Situations might arise when the application
452 //logmacros encounters such a serious error that can only be adequately treated
453 //logmacros by, for example, safely shutting down the application.
456 #define NOBUG_ALERT(flag, ...) \
457 NOBUG_ALERT_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
459 #define NOBUG_ALERT_IF(expr, flag, ...) \
460 NOBUG_ALERT_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
463 #define NOBUG_ALERT_CTX(flag, context, ...) \
464 NOBUG_LOG_CTX(flag, LOG_ALERT, context, ""__VA_ARGS__)
466 #define NOBUG_ALERT_IF_CTX(expr, flag, context, ...) \
467 NOBUG_LOG_IF(expr, flag, LOG_ALERT, context, ""__VA_ARGS__)
472 //logmacros PARA CRITICAL; CRITICAL; can not continue
474 //logmacros CRITICAL(flag, ...)
475 //logmacros CRITICAL_IF(when, flag, ...)
476 //logmacros NOBUG_CRITICAL_CTX(flag, context, ...)
477 //logmacros NOBUG_CRITICAL_IF_CTX(when, flag, context, ...)
479 //logmacros An error which can not be handled occured but the application does not need to be
480 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
483 #define NOBUG_CRITICAL(flag, ...) \
484 NOBUG_CRITICAL_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
486 #define NOBUG_CRITICAL_CTX(flag, context, ...) \
487 NOBUG_LOG_CTX(flag, LOG_CRIT, context, ""__VA_ARGS__)
490 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
491 NOBUG_CRITICAL_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
493 #define NOBUG_CRITICAL_IF_CTX(expr, flag, context, ...) \
494 NOBUG_LOG_IF_CTX(expr, flag, LOG_CRIT, context, ""__VA_ARGS__)
498 //logmacros PARA ERROR; ERROR; something gone wrong
500 //logmacros ERROR(flag, ...)
501 //logmacros ERROR_IF(when, flag, ...)
502 //logmacros NOBUG_ERROR_CTX(flag, context, ...)
503 //logmacros NOBUG_ERROR_IF_CTX(when, flag, context, ...)
505 //logmacros This is used when an application registers an error
506 //logmacros and appropriate action will have to be taken.
509 #define NOBUG_ERROR(flag, ...) \
510 NOBUG_ERROR_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
512 #define NOBUG_ERROR_CTX(flag, context, ...) \
513 NOBUG_LOG_CTX(flag, LOG_ERR, context, ""__VA_ARGS__)
516 #define NOBUG_ERROR_IF(expr, flag, ...) \
517 NOBUG_ERROR_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
519 #define NOBUG_ERROR_IF_CTX(expr, flag, context, ...) \
520 NOBUG_LOG_IF_CTX(expr, flag, LOG_ERR, context, ""__VA_ARGS__)
524 //logmacros PARA WARN; WARN; unexpected fixable error
526 //logmacros WARN(flag, ...)
527 //logmacros WARN_IF(when, flag, ...)
528 //logmacros NOBUG_WARN_CTX(flag, context, ...)
529 //logmacros NOBUG_WARN_IF_CTX(when, flag, context, ...)
531 //logmacros When an application encounters a rare and unexpected
532 //logmacros situation, these macros can be used.
535 #define NOBUG_WARN(flag, ...) \
536 NOBUG_WARN_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
538 #define NOBUG_WARN_CTX(flag, context, ...) \
539 NOBUG_LOG_CTX(flag, LOG_WARNING, context, ""__VA_ARGS__)
542 #define NOBUG_WARN_IF(expr, flag, ...) \
543 NOBUG_WARN_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
545 #define NOBUG_WARN_IF_CTX(expr, flag, context, ...) \
546 NOBUG_LOG_IF_CTX(expr, flag, LOG_WARNING, context, ""__VA_ARGS__)
550 //logmacros PARA INFO; INFO; progress message
552 //logmacros INFO(flag, ...)
553 //logmacros INFO_IF(when, flag, ...)
554 //logmacros NOBUG_INFO_CTX(flag, context, ...)
555 //logmacros NOBUG_INFO_IF_CTX(when, flag, context, ...)
557 //logmacros It may be benificial to output information at various
558 //logmacros locations throughout the code, e.g., messages on programm
559 //logmacros progress.
562 #define NOBUG_INFO(flag, ...) \
563 NOBUG_INFO_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
565 #define NOBUG_INFO_CTX(flag, context, ...) \
566 NOBUG_LOG_CTX(flag, LOG_INFO, context, ""__VA_ARGS__)
569 #define NOBUG_INFO_IF(expr, flag, ...) \
570 NOBUG_INFO_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
572 #define NOBUG_INFO_IF_CTX(expr, flag, context, ...) \
573 NOBUG_LOG_IF_CTX(expr, flag, LOG_INFO, context, ""__VA_ARGS__)
577 //logmacros PARA NOTICE; NOTICE; detailed progress message
579 //logmacros NOTICE(flag, ...)
580 //logmacros NOTICE_IF(when, flag, ...)
581 //logmacros NOBUG_NOTICE_CTX(flag, context, ...)
582 //logmacros NOBUG_NOTICE_IF_CTX(when, flag, context, ...)
584 //logmacros Same as the INFO() macros, except more verbose.
587 #define NOBUG_NOTICE(flag, ...) \
588 NOBUG_NOTICE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
590 #define NOBUG_NOTICE_CTX(flag, context, ...) \
591 NOBUG_LOG_CTX(flag, LOG_NOTICE, context, ""__VA_ARGS__)
594 #define NOBUG_NOTICE_IF(expr, flag, ...) \
595 NOBUG_NOTICE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
597 #define NOBUG_NOTICE_IF_CTX(expr, flag, context, ...) \
598 NOBUG_LOG_IF_CTX(expr, flag, LOG_NOTICE, context, ""__VA_ARGS__)
601 //logmacros PARA TRACE; TRACE; debugging level message
603 //logmacros TRACE(flag, ...)
604 //logmacros TRACE_IF(when, flag, ...)
605 //logmacros NOBUG_TRACE_CTX(flag, context, ...)
606 //logmacros NOBUG_TRACE_IF_CTX(when, flag, context, ...)
608 //logmacros The same as the NOTICE() macros, except very fine-grained information.
609 //logmacros a common use case is to put just `TRACE(debugflag)` just at the begin of every
610 //logmacros non-trivial function. This allows to watch fine grained application progress in the log.
612 //logmacros NOTE: `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
615 #define NOBUG_TRACE(flag, ...) \
616 NOBUG_TRACE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
618 #define NOBUG_TRACE_CTX(flag, context, ...) \
619 NOBUG_LOG_CTX(flag, LOG_DEBUG, context, ""__VA_ARGS__)
622 #define NOBUG_TRACE_IF(expr, flag, ...) \
623 NOBUG_TRACE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
625 #define NOBUG_TRACE_IF_CTX(expr, flag, context, ...) \
626 NOBUG_LOG_IF_CTX(expr, flag, LOG_DEBUG, context, ""__VA_ARGS__)
630 //logmacros PARA LOG; LOG; generic logging
632 //logmacros NOBUG_LOG_CTX(flag, lvl, context, ...)
633 //logmacros NOBUG_LOG_IF_CTX(when, flag, lvl, context, ...)
635 //logmacros Generic logging macro which takes the level explicitly.
636 //logmacros Avoid this, unless you implement your own logging facilities.
639 #define NOBUG_LOG_CTX(flag, lvl, context, ...) \
640 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LVL(lvl), context, ""__VA_ARGS__)
643 #define NOBUG_LOG_IF_CTX(expr, flag, lvl, context, ...) \
645 NOBUG_LOG_CTX(flag, lvl, context, ""__VA_ARGS__) \
649 //logmacros INDEX LOG_EMERG; LOG_EMERG; no logging macro for emergency logging
651 //logmacros NOTE: there is no logging macro for `LOG_EMERG`, this is only used by the assertions as a fatal message
656 low level logging handler
658 Note: all fmt concatenations use an empty string ""__VA_ARG__
659 except this one which must use a single space " " before __VA_ARGS__ for formatting the log message correctly (and silence a gcc warning)
661 #define NOBUG_LOG_(flag, lvl, what, context, ...) \
662 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
663 nobug_log (flag, lvl, what, context, " "__VA_ARGS__) \
667 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
668 #define NOBUG_LVL_0 "EMERG"
669 #define NOBUG_LVL_1 "ALERT"
670 #define NOBUG_LVL_2 "CRIT"
671 #define NOBUG_LVL_3 "ERR"
672 #define NOBUG_LVL_4 "WARNING"
673 #define NOBUG_LVL_5 "NOTICE"
674 #define NOBUG_LVL_6 "INFO"
675 #define NOBUG_LVL_7 "TRACE"
678 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
680 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
681 //logmacros NOBUG_LOG_BASELIMIT_BETA
682 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
683 //logmacros NOBUG_LOG_BASELIMIT
685 //logmacros Anything more detailed than this base limits will be optimized out.
686 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
687 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
688 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
689 //logmacros builds to log the application progress only coarsely.
691 //logmacros These macros can be defined before including 'nobug.h' to some other
692 //logmacros log level (as defined in 'syslog.h').
695 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
696 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
699 #ifndef NOBUG_LOG_BASELIMIT_BETA
700 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
703 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
704 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
707 #ifndef NOBUG_LOG_BASELIMIT
708 #define NOBUG_LOG_BASELIMIT \
709 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
710 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
711 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
716 //srccontext HEAD~ Source Contexts; NOBUG_CONTEXT; pass information about the source location
718 //srccontext NOBUG_CONTEXT
719 //srccontext NOBUG_CONTEXT_NOFUNC
721 //srccontext NoBug passes information about the source location of a given statement in
722 //srccontext `const struct nobug_context` structures. These can be generated with
723 //srccontext `NOBUG_CONTEXT` or `NOBUG_CONTEXT_NOFUNC`. The later one doesn't define a
724 //srccontext function name and must be used when the function context is not available
725 //srccontext like in static initialization etc..
730 #define NOBUG_CONTEXT ((const struct nobug_context){__FILE__, __LINE__, NOBUG_FUNC})
732 #define NOBUG_CONTEXT_NOFUNC ((const struct nobug_context){__FILE__, __LINE__, "-"})
734 #define NOBUG_CONTEXT_NIL ((const struct nobug_context){"-", 0, "-"})
737 #define NOBUG_CONTEXT (nobug_context(__FILE__, __LINE__, NOBUG_FUNC))
739 #define NOBUG_CONTEXT_NOFUNC (nobug_context(__FILE__, __LINE__, "-"))
741 #define NOBUG_CONTEXT_NIL (nobug_context("-", 0, "-"))
745 //annotations HEAD- Source Code Annotations;;
747 //annotations Obsolete, buggy or precarious code can be marked in the code itself in
748 //annotations comments at the location where the code occurs. However these code
749 //annotations locations can be easily overlooked, especially in large projects. NoBug
750 //annotations provides macros to tag code with such annotations. This provides an additional
751 //annotations instrument to alert or remind the programmer that there is still dubious
752 //annotations code embedded in the application. This tagging scheme not only informs
753 //annotations the programmer at compile time that there is code in the application
754 //annotations that needs attending to, but long after compilitation a test team
755 //annotations might become aware of dubious code due to runtime messages.
761 DEPRECATED log nothing wont compile
764 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
766 //annotations DEPRECATED(...)
768 //annotations Use this macro to identify code that is depreciated
769 //annotations and should not be used in future or productive code.
772 #define NOBUG_DEPRECATED(...) \
773 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
774 "DEPRECATED", NOBUG_CONTEXT, ""__VA_ARGS__) \
776 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
781 UNIMPLEMENTED abort abort wont compile
783 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
785 //annotations UNIMPLEMENTED(...)
787 //annotations Use this macro to identify code that is functionally
788 //annotations not yet complete and should not be used. This is convenient
789 //annotations for code under development or being reviewed.
792 #define NOBUG_UNIMPLEMENTED(...) \
793 NOBUG_IF_NOT_RELEASE ( do { \
794 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, \
795 "UNIMPLEMENTED", NOBUG_CONTEXT, ""__VA_ARGS__); \
798 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
803 FIXME log wont compile wont compile
805 //annotations PARA FIXME; FIXME; known bug
807 //annotations FIXME(...)
809 //annotations Use this macro to mark a known and unfixed bug.
812 #define NOBUG_FIXME(...) \
813 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
814 "FIXME", NOBUG_CONTEXT, ""__VA_ARGS__))) \
815 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__)) \
816 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
821 TODO log log wont compile
823 //annotations PARA TODO; TODO; things to be done
825 //annotations TODO(...)
827 //annotations Enhancement or non-critical bug to be done soon.
830 #define NOBUG_TODO(...) \
831 NOBUG_IF_NOT_RELEASE ( \
833 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, \
834 "TODO", NOBUG_CONTEXT, ""__VA_ARGS__); \
836 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
841 PLANNED log nothing nothing
843 //annotations PARA PLANNED; PLANNED; ideas for future
845 //annotations PLANNED(...)
847 //annotations Future enhancement, optimization to similar which has no side effect on the current program.
850 #define NOBUG_PLANNED(...) \
851 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
852 "PLANNED", NOBUG_CONTEXT, ""__VA_ARGS__)))
857 NOTREACHED abort abort nothing
859 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
861 //annotations NOTREACHED(...)
863 //annotations Code which must never be reached.
866 #define NOBUG_NOTREACHED(...) \
867 NOBUG_IF_NOT_RELEASE( do { \
868 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
869 "NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
875 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
877 //annotations ELSE_NOTREACHED(...)
879 //annotations This macro is the same as `else NOTREACHED()`, but completely
880 //annotations optimized out in release builds.
883 #define NOBUG_ELSE_NOTREACHED(...) \
884 NOBUG_IF_NOT_RELEASE( else do { \
885 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
886 "ELSE_NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
892 //faultinjection HEAD- Fault injection;;
894 //faultinjection NoBug has some macros which can be used to simulate erroneous behaviour,
895 //faultinjection in other words, we can inject errors, or faults, into the code
896 //faultinjection using NoBug.
898 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
900 //faultinjection INJECT_GOODBAD(expr, good, bad)
902 //faultinjection Substitutes to an expression and returns 'good' when expr is false and
903 //faultinjection 'bad' when expr is true. In BETA and RELEASE builds 'good' is always returned.
906 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
907 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);bad;}):good) \
908 NOBUG_IF_NOT_ALPHA(good)
912 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
914 //faultinjection INJECT_FAULT(expr, bad)
916 //faultinjection Substitutes to a statement which executes 'bad'
917 //faultinjection when expr is true. This is only available in ALPHA builds and
918 //faultinjection is optimitsed out in BETA and RELEASE builds.
921 #define NOBUG_INJECT_FAULT(expr, bad) \
922 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
926 //faultinjection PARA Setting the logging level for fault injections; INJECT_LEVEL; log level for fault injection
927 //faultinjection In both cases, when a fault is injected, it will be logged at
928 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
929 //faultinjection before including 'nobug.h' to override it.
932 #define NOBUG_INJECT_LOG(msg) \
933 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
934 "INJECT_FAULT", NOBUG_CONTEXT, \
938 #ifndef NOBUG_INJECT_LEVEL
939 #define NOBUG_INJECT_LEVEL LOG_NOTICE
944 //coverage HEAD~ Coverage checking Macros;;
946 //coverage PARA COVERAGE_FAULT; COVERAGE_FAULT; coverage fault injection, statement
948 //coverage COVERAGE_FAULT(flag, ...)
950 //coverage Injects the statement at `...` when simulating a failure. Only active in
951 //coverage ALPHA builds.
954 #define NOBUG_COVERAGE_FAULT(flag, ...) \
955 NOBUG_IF_ALPHA(NOBUG_COVERAGE_FAULT_(flag, __VA_ARGS__)) \
956 NOBUG_IF_NOT_ALPHA(__VA_ARGS__)
959 #define NOBUG_COVERAGE_FAULT_(flag, ...) \
961 if (!nobug_thread_get ()->coverage_disable_cnt) \
963 struct nobug_coverage_record record = nobug_coverage_check (); \
966 NOBUG_COVERAGE_LOG(flag, record); \
967 if (record.state == 'F') \
978 //coverage PARA COVERAGE_GOODBAD; COVERAGE_GOODBAD; coverage fault injection, expression
980 //coverage COVERAGE_GOODBAD(flag, good, bad)
982 //coverage Substitutes to an expression and injects `bad` when simulating a failure and `good`
983 //coverage otherwise. Only active in ALPHA builds.
986 #define NOBUG_COVERAGE_GOODBAD(flag, good, bad) \
987 NOBUG_IF_ALPHA(NOBUG_COVERAGE_GOODBAD_(flag, good, bad)) \
988 NOBUG_IF_NOT_ALPHA((good))
990 #define NOBUG_COVERAGE_GOODBAD_(flag, good, bad) \
992 struct nobug_coverage_record record = {0,0}; \
993 if (!nobug_thread_get ()->coverage_disable_cnt) \
995 record = nobug_coverage_check (); \
997 NOBUG_COVERAGE_LOG(flag, record); \
999 record.state == 'F'?(bad):(good); \
1005 #define NOBUG_COVERAGE_LOG(flag, record) \
1006 NOBUG_LOG_( &NOBUG_FLAG(flag), NOBUG_COVERAGE_LEVEL, \
1007 "COVERAGE", NOBUG_CONTEXT, \
1008 "INJECT %"PRIx64": %s", \
1010 record.state == 'F'?"FAILURE":"PASS")
1014 //coverage PARA COVERAGE_LEVEL; COVERAGE_LEVEL; coverage fault injection log level
1016 //coverage #define NOBUG_COVERAGE_LEVEL ...
1018 //coverage Define the logging level in which fault-coverage logging is emitted.
1020 //coverage NOTE: Supressing log output with this level will not supress fault injection,
1021 //coverage actually the opposite is true since every newly seen failure path gets injected.
1022 //coverage This might be changed in future releases.
1024 // TODO see above, disable fault injection when not logged
1025 // if (NOBUG_EXPECT_FALSE(NOBUG_COVERAGE_LEVEL <= flag->limits[NOBUG_TARGET_???]))
1028 #ifndef NOBUG_COVERAGE_LEVEL
1029 #define NOBUG_COVERAGE_LEVEL LOG_NOTICE
1035 //coverage PARA Disabling and enabling fault-coverage checks; COVERAGE_DISABLE; handle false positives
1037 //coverage NOBUG_COVERAGE_DISABLE
1038 //coverage NOBUG_COVERAGE_ENABLE
1040 //coverage Sometimes fault injection yields false positives, errors which may never happen in real life
1041 //coverage (and are possibly enforced with an ENSURE afterwards). For this cases coverage fault injection can be
1042 //coverage disabled temporarly and reenabled later. Disabling/enabling may nest and must properly match.
1046 #define NOBUG_COVERAGE_DISABLE \
1047 NOBUG_IF_ALPHA(unsigned nobug_coverage_disable_check = \
1048 nobug_thread_get ()->coverage_disable_cnt;) \
1049 NOBUG_IF_ALPHA(++ nobug_thread_get ()->coverage_disable_cnt)
1051 #define NOBUG_COVERAGE_ENABLE \
1052 NOBUG_IF_ALPHA(-- nobug_thread_get ()->coverage_disable_cnt); \
1053 ENSURE(nobug_coverage_disable_check == \
1054 nobug_thread_get ()->coverage_disable_cnt, \
1055 "COVERAGE ENABLE/DISABLE does not match")
1061 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
1063 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
1066 #define NOBUG_DEFINE_FLAG(name) \
1067 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1068 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1069 struct nobug_flag NOBUG_FLAG(name) = \
1070 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
1071 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1072 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
1073 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1074 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
1075 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1079 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
1080 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1081 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1082 NOBUG_DECLARE_FLAG(parent); \
1083 struct nobug_flag NOBUG_FLAG(name) = \
1084 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
1085 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1086 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
1087 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1088 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
1089 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1093 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
1094 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1095 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1096 struct nobug_flag NOBUG_FLAG(name) = \
1097 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
1098 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1099 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
1100 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1101 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
1102 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1106 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
1107 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
1108 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
1109 NOBUG_DECLARE_FLAG(parent); \
1110 struct nobug_flag NOBUG_FLAG(name) = \
1111 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
1112 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
1113 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
1114 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
1115 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
1116 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
1120 #define NOBUG_INIT_FLAG(name) \
1121 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT, NOBUG_CONTEXT_NOFUNC)
1124 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
1125 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default, NOBUG_CONTEXT_NOFUNC)
1128 #define NOBUG_CPP_DEFINE_FLAG(name) \
1129 NOBUG_FLAG_IF_DECLAREONLY( \
1130 NOBUG_DECLARE_FLAG(name); \
1131 extern int nobug_cppflag_##name \
1133 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1134 NOBUG_DEFINE_FLAG(name); \
1135 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
1139 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
1140 NOBUG_FLAG_IF_DECLAREONLY( \
1141 NOBUG_DECLARE_FLAG(name); \
1142 extern int nobug_cppflag_##name \
1144 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1145 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
1146 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
1150 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
1151 NOBUG_FLAG_IF_DECLAREONLY( \
1152 NOBUG_DECLARE_FLAG(name); \
1153 extern int nobug_cppflag_##name \
1155 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1156 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
1157 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
1161 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
1162 NOBUG_FLAG_IF_DECLAREONLY( \
1163 NOBUG_DECLARE_FLAG(name); \
1164 extern int nobug_cppflag_##name \
1166 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
1167 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
1168 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
1172 #ifndef NOBUG_DECLARE_ONLY
1173 #define NOBUG_DECLARE_ONLY 0
1176 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
1177 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1179 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
1180 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1183 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
1184 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
1186 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
1187 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
1190 #ifndef NOBUG_LOG_LIMIT_ALPHA
1191 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
1193 #ifndef NOBUG_LOG_LIMIT_BETA
1194 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
1196 #ifndef NOBUG_LOG_LIMIT_RELEASE
1197 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
1200 #ifndef NOBUG_LOG_LIMIT
1201 # define NOBUG_LOG_LIMIT \
1202 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
1203 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
1204 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
1207 #ifndef NOBUG_LOG_TARGET_ALPHA
1208 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
1210 #ifndef NOBUG_LOG_TARGET_BETA
1211 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
1213 #ifndef NOBUG_LOG_TARGET_RELEASE
1214 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
1217 #ifndef NOBUG_LOG_TARGET
1218 # define NOBUG_LOG_TARGET \
1219 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
1220 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
1221 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
1224 #define NOBUG_SET_LIMIT(flag, min) \
1225 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
1229 //resourcemacros HEAD~ Resource tracking macros;;
1230 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
1231 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
1233 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
1234 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
1235 //resourcemacros `LOG_DEBUG`.
1238 #ifndef NOBUG_RESOURCE_LOGGING
1239 #define NOBUG_RESOURCE_LOGGING 1
1242 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1243 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1248 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
1250 //resourcemacros RESOURCE_HANDLE(name)
1251 //resourcemacros RESOURCE_HANDLE_INIT(name)
1252 //resourcemacros RESOURCE_USER(name)
1253 //resourcemacros RESOURCE_USER_INIT(name)
1255 //resourcemacros Define and initialize handles for to track resources.
1257 //resourcemacros `name`::
1258 //resourcemacros identifer to be used for the handle
1260 //resourcemacros There are two kinds of handles. Resource themself are abstracted with a
1261 //resourcemacros `RESOURCE_HANDLE` while uses of a resources are tracked by `RESOURCE_USER`
1262 //resourcemacros handle. These macros takes care that the declaration is optimized out
1263 //resourcemacros in the same manner as the rest of the resource tracker would be disabled.
1264 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
1265 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
1266 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
1267 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
1270 #define NOBUG_RESOURCE_HANDLE(handle) \
1271 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1273 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1275 #define NOBUG_RESOURCE_USER(handle) \
1276 NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
1278 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1282 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
1284 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle){}
1285 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW(flagptr, type, name, ptr, handle){}
1286 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flagptr, type, name,
1287 //resourcemacros ptr, handle, context){}
1289 //resourcemacros Publishes resources.
1291 //resourcemacros `flag`::
1292 //resourcemacros the NoBug flag name which turns logging on for this macro
1293 //resourcemacros `type`::
1294 //resourcemacros a string which should denote the domain of the resource,
1295 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1296 //resourcemacros `name`::
1297 //resourcemacros the actual name of a named resource this as string. `type` and
1298 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1299 //resourcemacros literal strings is recommended
1300 //resourcemacros `identifier`::
1301 //resourcemacros a pointer which must be unique for this resource, any
1302 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1303 //resourcemacros multithreaded applications the thread identifier becomes an additional
1304 //resourcemacros identifier
1305 //resourcemacros `handle`::
1306 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1307 //resourcemacros the newly created resource.
1309 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1310 //resourcemacros announced more than one time.
1312 //resourcemacros `RESOURCE_ANNOUNCE()` acts like the head of a C loop statement, it ties to the following
1313 //resourcemacros (block-) statement which will be handled atomic.
1314 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1317 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1318 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(&NOBUG_FLAG(flag), type, name, ptr, handle, NOBUG_CONTEXT)
1321 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1322 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, NOBUG_CONTEXT)
1325 #define NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, context) \
1326 NOBUG_IF_NOT_RELEASE( for ( \
1327 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1329 NOBUG_REQUIRE_CTX(!handle, context, "Announced resource handle not initialized"); \
1330 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1331 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1332 "RESOURCE_ANNOUNCE", context, \
1333 "%s: %s@%p", type, name, ptr);) \
1335 NOBUG_RESOURCE_ASSERT_CTX(handle = nobug_resource_announce (type, name, \
1338 "RESOURCE_ASSERT_ANNOUNCE", context, \
1339 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1345 NOBUG_IF_ALPHA (nobug_resource_announce_complete ();) \
1351 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1353 //resourcemacros RESOURCE_FORGET(flag, handle){}
1354 //resourcemacros NOBUG_RESOURCE_FORGET_RAW(flagptr, handle){}
1355 //resourcemacros NOBUG_RESOURCE_FORGET_RAW_CTX(flagptr, handle, context){}
1357 //resourcemacros Removes resources that have become unavailable from the registry.
1359 //resourcemacros `flag`::
1360 //resourcemacros the NoBug flag which turns logging on for this macro
1361 //resourcemacros `handle`::
1362 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1364 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1365 //resourcemacros error is raised.
1367 //resourcemacros `RESOURCE_FORGET()` acts like the head of a C loop statement, it ties to the following
1368 //resourcemacros (block-) statement which will be handled atomic.
1369 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1372 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1373 NOBUG_RESOURCE_FORGET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1375 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1376 NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1378 #define NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, context) \
1379 NOBUG_IF_NOT_RELEASE( for ( \
1380 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1382 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1383 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1384 "RESOURCE_FORGET", context, "%s: %s@%p", \
1385 (handle)?(handle)->type:"", \
1386 (handle)?(handle)->hdr.name:"", \
1387 (handle)?(handle)->object_id:NULL);) \
1393 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_forget (handle), \
1394 "RESOURCE_ASSERT_FORGET", context, "%s: %s@%p: %s", \
1395 (handle)?(handle)->type:"", \
1396 (handle)?(handle)->hdr.name:"", \
1397 (handle)?(handle)->object_id:NULL, \
1398 nobug_resource_error); \
1406 //resourcemacros PARA RESOURCE_RESETALL; RESOURCE_RESETALL; reset the resource tracker to a pristine state
1408 //resourcemacros RESOURCE_RESETALL(flag)
1409 //resourcemacros NOBUG_RESOURCE_RESETALL_RAW(flagptr)
1410 //resourcemacros NOBUG_RESOURCE_RESETALL_RAW_CTX(flagptr, context)
1412 //resourcemacros Sometimes the resource tracker can give false positives when it finds a locking order violation
1413 //resourcemacros while the programmer knows that this will never happen in the real program, because for example
1414 //resourcemacros this is only used at initialization or shutdown and never overlaps. This macro can then be used
1415 //resourcemacros to reset all whats learnt about all resources and start over.
1417 //resourcemacros `flag`::
1418 //resourcemacros the NoBug flag which turns logging on for this macro
1421 #define NOBUG_RESOURCE_RESETALL(flag) \
1422 NOBUG_RESOURCE_RESETALL_RAW_CTX(&NOBUG_FLAG(flag), NOBUG_CONTEXT)
1424 #define NOBUG_RESOURCE_RESETALL_RAW(flag) \
1425 NOBUG_RESOURCE_RESETALL_RAW_CTX(flag, NOBUG_CONTEXT)
1427 #define NOBUG_RESOURCE_RESETALL_RAW_CTX(flag, context) \
1429 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_resetall (), \
1430 "RESOURCE_ASSERT_RESETALL", context, "%s", \
1431 nobug_resource_error))
1436 //resourcemacros PARA RESOURCE_RESET; RESOURCE_RESET; reset a single resource to a pristine state
1438 //resourcemacros RESOURCE_RESET(flag, handle)
1439 //resourcemacros NOBUG_RESOURCE_RESET_RAW(flagptr, handle)
1440 //resourcemacros NOBUG_RESOURCE_RESET_RAW_CTX(flagptr, handle, context)
1442 //resourcemacros Sometimes the resource tracker can give false positives when it finds a locking order violation
1443 //resourcemacros while the programmer knows that this will never happen in the real program, because for example
1444 //resourcemacros this is only used at initialization or shutdown and never overlaps. This macro can then be used
1445 //resourcemacros to reset all whats learnt about a single resources and start over.
1447 //resourcemacros `flag`::
1448 //resourcemacros the NoBug flag which turns logging on for this macro
1449 //resourcemacros `handle`::
1450 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1453 #define NOBUG_RESOURCE_RESET(flag, handle) \
1454 NOBUG_RESOURCE_RESET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1456 #define NOBUG_RESOURCE_RESET_RAW(flag, handle) \
1457 NOBUG_RESOURCE_RESET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1459 #define NOBUG_RESOURCE_RESET_RAW_CTX(flag, handle, context) \
1461 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_reset (handle), \
1462 "RESOURCE_ASSERT_RESET", context, \
1464 (handle)?(handle)->type:"", \
1465 (handle)?(handle)->hdr.name:"", \
1466 (handle)?(handle)->object_id:NULL, \
1467 nobug_resource_error))
1472 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1474 //resourcemacros RESOURCE_ENTER(flag, announced, user, state, handle){}
1475 //resourcemacros NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state,
1476 //resourcemacros handle, context){}
1478 //resourcemacros Acquire a resource.
1480 //resourcemacros `flag`::
1481 //resourcemacros nobug flag which turns logging on for this macro
1482 //resourcemacros `announced`::
1483 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1484 //resourcemacros `user`::
1485 //resourcemacros a literal string defining the purpose
1486 //resourcemacros `state`::
1487 //resourcemacros the state to enter
1488 //resourcemacros `handle`::
1489 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1490 //resourcemacros entering node
1492 //resourcemacros `RESOURCE_ENTER()` acts like the head of a C loop statement, it ties to the following
1493 //resourcemacros (block-) statement which will be handled atomic.
1494 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1497 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1498 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, NOBUG_CONTEXT)
1501 #define NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context) \
1502 NOBUG_IF_NOT_RELEASE( for ( \
1503 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1505 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1506 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1507 "RESOURCE_ENTER", context, \
1508 "%s: %s@%p: %s: %s", \
1509 (resource)?(resource)->type:"", \
1510 (resource)?(resource)->hdr.name:"", \
1511 (resource)?(resource)->object_id:NULL, \
1513 nobug_resource_states[state]);) \
1515 NOBUG_RESOURCE_ASSERT_CTX(handle = \
1516 nobug_resource_enter (resource, \
1519 "RESOURCE_ASSERT_ENTER", context, \
1520 "%s: %s@%p: %s: %s: %s", \
1521 (resource)?(resource)->type:"", \
1522 (resource)?(resource)->hdr.name:"", \
1523 (resource)?(resource)->object_id:NULL, \
1524 user, nobug_resource_states[state], \
1525 nobug_resource_error);) \
1533 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1535 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle){}
1536 //resourcemacros NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context){}
1538 //resourcemacros This is just an alias for
1540 //resourcemacros RESOURCE_ENTER(flag, resource, user,
1541 //resourcemacros NOBUG_RESOURCE_WAITING, handle)
1543 //resourcemacros .How to use it
1544 //resourcemacros [source,c]
1545 //resourcemacros ----
1546 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle);
1547 //resourcemacros if (lock_my_resource() == ERROR)
1548 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle);
1549 //resourcemacros else
1550 //resourcemacros RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1551 //resourcemacros ----
1553 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1554 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1556 #define NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context) \
1557 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_WAITING, handle, context)
1560 //resourcemacros PARA RESOURCE_TRY; RESOURCE_TRY; wait for a resource to become available
1562 //resourcemacros RESOURCE_TRY(flag, resource, user, handle){}
1563 //resourcemacros NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context){}
1565 //resourcemacros This is just an alias for
1567 //resourcemacros RESOURCE_ENTER(flag, resource, user,
1568 //resourcemacros NOBUG_RESOURCE_TRYING, handle)
1570 //resourcemacros Trying on a resource is similar to waiting but will not trigger a deadlock check. This can be used
1571 //resourcemacros when a deadlock is expected at runtime and one handles this otherwise (by a timed wait or something like that).
1573 #define NOBUG_RESOURCE_TRY(flag, resource, user, handle) \
1574 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle)
1576 #define NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context) \
1577 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_TRYING, handle, context)
1581 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1583 //resourcemacros RESOURCE_STATE(flag, entered, state){}
1584 //resourcemacros NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context){}
1585 //resourcemacros NOBUG_RESOURCE_STATE_RAW(flagptr, state, entered){}
1586 //resourcemacros NOBUG_RESOURCE_STATE_RAW_CTX(flagptr, state, entered, context){}
1588 //resourcemacros Changes resource's state.
1590 //resourcemacros `flag`::
1591 //resourcemacros is nobug flag which turns logging on for this macro
1592 //resourcemacros `state`::
1593 //resourcemacros the new state Note that only certain state transitions are
1594 //resourcemacros allowed, see discussion/diagram above
1595 //resourcemacros `entered`::
1596 //resourcemacros the handle set by `RESOURCE_ENTER`
1598 //resourcemacros `RESOURCE_STATE()` acts like the head of a C loop statement, it ties to the following
1599 //resourcemacros (block-) statement which will be handled atomic.
1600 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1603 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1604 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, NOBUG_CONTEXT)
1606 #define NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context) \
1607 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, context)
1609 #define NOBUG_RESOURCE_STATE_RAW(flag, state, entered) \
1610 NOBUG_RESOURCE_STATE_RAW_CTX(flag, state, entered, NOBUG_CONTEXT)
1612 #define NOBUG_RESOURCE_STATE_RAW_CTX(flag, nstate, entered, context) \
1613 NOBUG_IF_NOT_RELEASE( for ( \
1614 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = \
1616 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1617 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1618 "RESOURCE_STATE", context, \
1619 "%s: %s@%p: %s: %s->%s", \
1620 (entered)?(entered)->current->resource->type:"", \
1621 (entered)?(entered)->current->resource->hdr.name:"", \
1622 (entered)?(entered)->current->resource->object_id:"", \
1623 (entered)?(entered)->hdr.name:"", \
1624 nobug_resource_states[(entered)?(entered)->state \
1625 :NOBUG_RESOURCE_INVALID], \
1626 nobug_resource_states[nstate]); \
1629 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_state ((entered), nstate), \
1630 "RESOURCE_ASSERT_STATE", context, \
1631 "%s: %s@%p: %s: %s->%s: %s", \
1632 (entered)?(entered)->current->resource->type:"", \
1633 (entered)?(entered)->current->resource->hdr.name:"", \
1634 (entered)?(entered)->current->resource->object_id:"", \
1635 (entered)?(entered)->hdr.name:"", \
1636 nobug_resource_states[(entered)?(entered)->state \
1637 :NOBUG_RESOURCE_INVALID], \
1638 nobug_resource_states[nstate], \
1639 nobug_resource_error); \
1647 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1649 //resourcemacros RESOURCE_LEAVE(flag, handle){}
1650 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW(flagptr, handle){}
1651 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW_CTX(flagptr, handle, context){}
1653 //resourcemacros Disconnect from a resource identified with its handle.
1655 //resourcemacros `flag`::
1656 //resourcemacros nobug flag which turns logging on for this macro
1657 //resourcemacros `handle`::
1658 //resourcemacros the handle you got while entering the resource
1660 //resourcemacros `RESOURCE_LEAVE()` acts like the head of a C loop statement, it ties to the following
1661 //resourcemacros (block-) statement which will be handled atomic.
1662 //resourcemacros This statement must not be left by break, return or any other kind of jump.
1664 //resourcemacros .How to use it
1665 //resourcemacros [source,c]
1666 //resourcemacros ----
1667 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle)
1669 //resourcemacros unlock_my_resource();
1671 //resourcemacros ----
1674 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1675 NOBUG_RESOURCE_LEAVE_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1677 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1678 NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1680 #define NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, context) \
1681 NOBUG_IF_NOT_RELEASE( \
1683 int NOBUG_CLEANUP(nobug_section_cleaned) section_ = ({ \
1684 nobug_resource_leave_pre(); \
1689 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1690 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1691 "RESOURCE_LEAVE", context, \
1692 "%s: %s@%p: %s: %s", \
1693 (handle)?(handle)->current->resource->type:"", \
1694 (handle)?(handle)->current->resource->hdr.name:"", \
1695 (handle)?(handle)->current->resource->object_id:"", \
1696 (handle)?(handle)->hdr.name:"", \
1697 nobug_resource_states[(handle)?(handle)->state \
1698 :NOBUG_RESOURCE_INVALID]); \
1701 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_leave (handle), \
1702 "RESOURCE_ASSERT_LEAVE", context, \
1703 "%s: %s@%p: %s: %s: %s", \
1704 (handle)?(handle)->current->resource->type:"", \
1705 (handle)?(handle)->current->resource->hdr.name:"", \
1706 (handle)?(handle)->current->resource->object_id:"", \
1707 (handle)?(handle)->hdr.name:"", \
1708 nobug_resource_states[(handle)?(handle)->state \
1709 :NOBUG_RESOURCE_INVALID], \
1710 nobug_resource_error); \
1717 //resourcemacros PARA RESOURCE_ASSERT_STATE; RESOURCE_ASSERT_STATE; assert the state of a resource
1719 //resourcemacros RESOURCE_ASSERT_STATE(resource, state)
1720 //resourcemacros RESOURCE_ASSERT_STATE_IF(when, resource, state)
1721 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context)
1722 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_IF_CTX(when, resource,
1723 //resourcemacros state, context)
1725 //resourcemacros Assert that we have a resource in a given state. For multithreaded programms the topmost
1726 //resourcemacros state of the calling thread is checked, for non threadeded programs the most recent state on
1727 //resourcemacros resource is used.
1729 //resourcemacros `when`::
1730 //resourcemacros Condition which must be true for testing the assertion
1731 //resourcemacros `resource`::
1732 //resourcemacros Resource handle
1733 //resourcemacros `state`::
1734 //resourcemacros The expected state
1737 #define NOBUG_RESOURCE_ASSERT_STATE(resource, state) \
1738 NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, NOBUG_CONTEXT)
1740 #define NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context) \
1743 enum nobug_resource_state mystate = nobug_resource_mystate (resource); \
1744 NOBUG_RESOURCE_ASSERT_CTX(mystate == state, \
1745 "RESOURCE_ASSERT_STATE", context, \
1746 "resource %p has state %s but %s was expected", \
1747 resource, nobug_resource_states[mystate], nobug_resource_states[state]); \
1751 #define NOBUG_RESOURCE_ASSERT_STATE_IF(when, resource, state) \
1752 NOBUG_WHEN(when, NOBUG_RESOURCE_ASSERT_STATE (resource, state))
1755 /* assertion which dumps all resources */
1756 #define NOBUG_RESOURCE_ASSERT_CTX(expr, what, context, ...) \
1758 NOBUG_WHEN (!(expr), \
1759 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1762 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1763 &nobug_flag_NOBUG_ON, \
1766 NOBUG_BACKTRACE_CTX(context); \
1771 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1773 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1774 //resourcemacros NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1776 //resourcemacros Dump the state of a single resource.
1778 //resourcemacros `when`::
1779 //resourcemacros Condition which must be true to dump the resource
1780 //resourcemacros `flag`::
1781 //resourcemacros Nobug flag for the log channel
1782 //resourcemacros `handle`::
1783 //resourcemacros handle of the resource to be dumped
1786 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1789 nobug_resource_dump (handle, NOBUG_RESOURCE_DUMP_CONTEXT( \
1790 &NOBUG_FLAG(flag), \
1791 NOBUG_RESOURCE_LOG_LEVEL, \
1795 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1798 nobug_resource_dump (handle, NOBUG_RESOURCE_DUMP_CONTEXT( \
1799 &NOBUG_FLAG(flag), \
1800 NOBUG_RESOURCE_LOG_LEVEL, \
1806 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1808 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1809 //resourcemacros NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1811 //resourcemacros Dump the state of all resources.
1813 //resourcemacros `when`::
1814 //resourcemacros Condition which must be true to dump the resources
1815 //resourcemacros `flag`::
1816 //resourcemacros Nobug flag for the log channel
1819 #define NOBUG_RESOURCE_DUMPALL(flag) \
1822 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1823 &NOBUG_FLAG(flag), \
1824 NOBUG_RESOURCE_LOG_LEVEL, \
1829 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1832 nobug_resource_dump_all (NOBUG_RESOURCE_DUMP_CONTEXT( \
1833 &NOBUG_FLAG(flag), \
1834 NOBUG_RESOURCE_LOG_LEVEL, \
1839 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1841 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1842 //resourcemacros NOBUG_RESOURCE_LIST_IF(when, flag)
1844 //resourcemacros List all registered resources.
1846 //resourcemacros `when`::
1847 //resourcemacros Condition which must be true to list the resources
1848 //resourcemacros `flag`::
1849 //resourcemacros Nobug flag for the log channel
1852 #define NOBUG_RESOURCE_LIST(flag) \
1855 nobug_resource_list (NOBUG_RESOURCE_DUMP_CONTEXT( \
1856 &NOBUG_FLAG(flag), \
1857 NOBUG_RESOURCE_LOG_LEVEL, \
1862 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1865 nobug_resource_list (NOBUG_RESOURCE_DUMP_CONTEXT( \
1866 &NOBUG_FLAG(flag), \
1867 NOBUG_RESOURCE_LOG_LEVEL, \
1872 /* constructing a resource-dump context */
1874 #define NOBUG_RESOURCE_DUMP_CONTEXT(flag, level, context) \
1875 ((struct nobug_resource_dump_context){ \
1880 #define NOBUG_CONTEXT (nobug_context(__FILE__, __LINE__, NOBUG_FUNC))
1881 #define NOBUG_RESOURCE_DUMP_CONTEXT(flag, level, context) \
1882 (nobug_resource_dump_context(flag, level, context))
1889 #if NOBUG_USE_PTHREAD
1890 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1891 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1894 #define NOBUG_THREAD_ID_SET(name)
1895 #define NOBUG_THREAD_ID_GET ""
1898 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1905 #define NOBUG_DBG_NONE 0
1906 #define NOBUG_DBG_GDB 1
1907 #define NOBUG_DBG_VALGRIND 2
1909 #define NOBUG_ACTIVE_DBG \
1910 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1911 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1914 //toolmacros HEAD- Tool Macros;;
1916 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1918 //toolmacros NOBUG_FLAG_RAW(ptr)
1920 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1921 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1922 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1924 //toolmacros [source,c]
1926 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1928 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1929 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1933 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1936 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1938 //toolmacros BACKTRACE
1939 //toolmacros NOBUG_BACKTRACE_CTX(context)
1941 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1942 //toolmacros This is automatically called when NoBug finds an error and is due
1943 //toolmacros to abort. But one might call it manually too.
1946 #define NOBUG_BACKTRACE NOBUG_BACKTRACE_CTX(NOBUG_CONTEXT)
1948 #define NOBUG_BACKTRACE_CTX(context) \
1950 switch (NOBUG_ACTIVE_DBG) { \
1951 case NOBUG_DBG_VALGRIND: \
1952 NOBUG_BACKTRACE_VALGRIND(context); \
1955 NOBUG_BACKTRACE_GLIBC(context); \
1957 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC(context))
1959 #define NOBUG_BACKTRACE_GDB(context) UNIMPLEMENTED
1961 #define NOBUG_BACKTRACE_VALGRIND(context) \
1962 NOBUG_IF(NOBUG_USE_VALGRIND, \
1963 nobug_backtrace_valgrind (context) \
1967 #ifndef NOBUG_BACKTRACE_DEPTH
1968 #define NOBUG_BACKTRACE_DEPTH 256
1971 #define NOBUG_BACKTRACE_GLIBC(context) \
1972 NOBUG_IF_NOT_RELEASE( \
1973 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1974 nobug_backtrace_glibc (context); \
1979 #define NOBUG_TAB " "
1982 //toolmacros PARA Aborting; ABORT; abort the program
1984 //toolmacros NOBUG_ABORT_
1986 //toolmacros This is the default implementation for aborting the program, it first syncs all ringbuffers to disk, then
1987 //toolmacros calls the abort callback if defined and then `abort()`.
1989 //toolmacros NOBUG_ABORT
1991 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1992 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1995 #define NOBUG_ABORT NOBUG_ABORT_
1998 #define NOBUG_ABORT_ \
2000 nobug_ringbuffer_allsync (); \
2001 if (nobug_abort_callback) \
2002 nobug_abort_callback (nobug_callback_data); \
2008 init and other function wrapers
2010 #define NOBUG_INIT nobug_init(NOBUG_CONTEXT)
2013 short macros without NOBUG_
2015 #ifndef NOBUG_DISABLE_SHORTNAMES
2017 #define REQUIRE NOBUG_REQUIRE
2020 #define REQUIRE_IF NOBUG_REQUIRE_IF
2023 #define ENSURE NOBUG_ENSURE
2026 #define ENSURE_IF NOBUG_ENSURE_IF
2029 #define ASSERT NOBUG_ASSERT
2032 #define ASSERT_IF NOBUG_ASSERT_IF
2035 #define CHECK NOBUG_CHECK
2038 #define CHECK NOBUG_CHECK
2041 #define INVARIANT NOBUG_INVARIANT
2043 #ifndef INVARIANT_IF
2044 #define INVARIANT_IF NOBUG_INVARIANT_IF
2046 #ifndef INVARIANT_ASSERT
2047 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
2049 #ifndef INVARIANT_ASSERT_IF
2050 #define INVARIANT_ASSERT_IF NOBUG_INVARIANT_ASSERT_IF
2053 #define DUMP NOBUG_DUMP
2056 #define DUMP_IF NOBUG_DUMP_IF
2059 #define DUMP_LOG NOBUG_DUMP_LOG
2062 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
2065 #define LOG NOBUG_LOG
2068 #define LOG_IF NOBUG_LOG_IF
2071 #define ECHO NOBUG_ECHO
2074 #define ALERT NOBUG_ALERT
2077 #define ALERT_IF NOBUG_ALERT_IF
2080 #define CRITICAL NOBUG_CRITICAL
2083 #define CRITICAL_IF NOBUG_CRITICAL_IF
2086 #define ERROR NOBUG_ERROR
2089 #define ERROR_IF NOBUG_ERROR_IF
2092 #define WARN NOBUG_WARN
2095 #define WARN_IF NOBUG_WARN_IF
2098 #define INFO NOBUG_INFO
2101 #define INFO_IF NOBUG_INFO_IF
2104 #define NOTICE NOBUG_NOTICE
2107 #define NOTICE_IF NOBUG_NOTICE_IF
2110 #define TRACE NOBUG_TRACE
2113 #define TRACE_IF NOBUG_TRACE_IF
2116 #define BACKTRACE NOBUG_BACKTRACE
2119 #define DEPRECATED NOBUG_DEPRECATED
2121 #ifndef UNIMPLEMENTED
2122 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
2125 #define FIXME NOBUG_FIXME
2128 #define TODO NOBUG_TODO
2131 #define PLANNED NOBUG_PLANNED
2134 #define NOTREACHED NOBUG_NOTREACHED
2136 #ifndef ELSE_NOTREACHED
2137 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
2139 #ifndef INJECT_GOODBAD
2140 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
2142 #ifndef INJECT_FAULT
2143 #define INJECT_FAULT NOBUG_INJECT_FAULT
2145 #ifndef COVERAGE_DISABLE
2146 #define COVERAGE_DISABLE NOBUG_COVERAGE_DISABLE
2148 #ifndef COVERAGE_ENABLE
2149 #define COVERAGE_ENABLE NOBUG_COVERAGE_ENABLE
2151 #ifndef COVERAGE_FAULT
2152 #define COVERAGE_FAULT NOBUG_COVERAGE_FAULT
2154 #ifndef COVERAGE_GOODBAD
2155 #define COVERAGE_GOODBAD NOBUG_COVERAGE_GOODBAD
2158 #define CLEANUP NOBUG_CLEANUP
2161 #define CHECKED NOBUG_CHECKED
2164 #define UNCHECKED NOBUG_UNCHECKED
2166 #ifndef RESOURCE_ANNOUNCE
2167 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
2169 #ifndef RESOURCE_FORGET
2170 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
2172 #ifndef RESOURCE_RESETALL
2173 #define RESOURCE_RESETALL NOBUG_RESOURCE_RESETALL
2175 #ifndef RESOURCE_RESET
2176 #define RESOURCE_RESET NOBUG_RESOURCE_RESET
2178 #ifndef RESOURCE_ENTER
2179 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
2181 #ifndef RESOURCE_WAIT
2182 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
2184 #ifndef RESOURCE_TRY
2185 #define RESOURCE_TRY NOBUG_RESOURCE_TRY
2187 #ifndef RESOURCE_STATE
2188 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
2190 #ifndef RESOURCE_LEAVE
2191 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
2193 #ifndef RESOURCE_LEAVE_LOOKUP
2194 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
2196 #ifndef RESOURCE_HANDLE
2197 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
2199 #ifndef RESOURCE_HANDLE_INIT
2200 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
2202 #ifndef RESOURCE_USER
2203 #define RESOURCE_USER NOBUG_RESOURCE_USER
2205 #ifndef RESOURCE_ASSERT_STATE
2206 #define RESOURCE_ASSERT_STATE NOBUG_RESOURCE_ASSERT_STATE
2208 #ifndef RESOURCE_ASSERT_STATE_IF
2209 #define RESOURCE_ASSERT_STATE_IF NOBUG_RESOURCE_ASSERT_STATE_IF
2211 #ifndef RESOURCE_USER_INIT
2212 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
2214 #ifndef RESOURCE_DUMP
2215 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
2217 #ifndef RESOURCE_DUMP_IF
2218 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
2220 #ifndef RESOURCE_DUMPALL
2221 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
2223 #ifndef RESOURCE_DUMPALL_IF
2224 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
2226 #ifndef RESOURCE_LIST
2227 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
2229 #ifndef RESOURCE_LIST_IF
2230 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
2232 #endif /* NOBUG_DISABLE_SHORTNAMES */
2239 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
2240 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
2242 #define NOBUG_CLEANUP(fn)
2243 #define NOBUG_ATTR_PRINTF(fmt, ell)
2247 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
2249 //toolmacros NOBUG_ALPHA_COMMA(something)
2250 //toolmacros NOBUG_ALPHA_COMMA_NULL
2252 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
2253 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
2254 //toolmacros use this macros to append a comma and something else only in *ALPHA* builds as in:
2256 //toolmacros [source,C]
2258 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
2261 //toolmacros Becomes the following in *ALPHA* builds
2263 //toolmacros [source,C]
2265 //toolmacros struct foo = {"foo", "bar", NULL};
2270 //toolmacros [source,C]
2272 //toolmacros struct foo = {"foo", "bar"};
2275 //toolmacros in *BETA* and *RELEASE* builds.
2278 #define NOBUG_COMMA ,
2279 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
2280 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
2282 #define NOBUG_ONCE(code) \
2284 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 1; \
2285 if (NOBUG_EXPECT_FALSE(NOBUG_CAT(nobug_once_,__LINE__))) \
2287 NOBUG_CAT(nobug_once_,__LINE__) = 0; \
2293 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
2295 #define NOBUG_EXPECT_FALSE(x) x
2298 #define NOBUG_WHEN(when, ...) \
2299 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
2302 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
2304 //toolmacros NOBUG_IF_ALPHA(...)
2305 //toolmacros NOBUG_IF_NOT_ALPHA(...)
2306 //toolmacros NOBUG_IF_BETA(...)
2307 //toolmacros NOBUG_IF_NOT_BETA(...)
2308 //toolmacros NOBUG_IF_RELEASE(...)
2309 //toolmacros NOBUG_IF_NOT_RELEASE(...)
2311 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
2312 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
2313 //toolmacros internally, but can also be used for custom things.
2316 #define NOBUG_IF_ALPHA(...) \
2317 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
2319 #define NOBUG_IF_NOT_ALPHA(...) \
2320 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
2322 #define NOBUG_IF_BETA(...) \
2323 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
2325 #define NOBUG_IF_NOT_BETA(...) \
2326 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
2328 #define NOBUG_IF_RELEASE(...) \
2329 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
2331 #define NOBUG_IF_NOT_RELEASE(...) \
2332 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
2335 preprocessor hacks/metaprogramming
2338 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
2339 #define NOBUG_IF_1(...) __VA_ARGS__
2340 #define NOBUG_IF_0(...)
2342 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
2344 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
2345 #define NOBUG_NOT_1 0
2346 #define NOBUG_NOT_0 1
2348 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
2349 #define NOBUG_AND_00 0
2350 #define NOBUG_AND_01 0
2351 #define NOBUG_AND_10 0
2352 #define NOBUG_AND_11 1
2354 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
2355 #define NOBUG_OR_00 0
2356 #define NOBUG_OR_01 1
2357 #define NOBUG_OR_10 1
2358 #define NOBUG_OR_11 1
2360 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
2361 #define NOBUG_XOR_00 0
2362 #define NOBUG_XOR_01 1
2363 #define NOBUG_XOR_10 1
2364 #define NOBUG_XOR_11 0
2366 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
2367 #define NOBUG_CAT_(a,b) a##b
2369 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
2370 #define NOBUG_CAT3_(a,b,c) a##b##c
2372 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
2373 #define NOBUG_STRINGIZE_(s) #s
2377 LIBNOBUG DECLARATIONS
2382 } /* fix emacs indent */
2385 #ifndef LLIST_DEFINED
2386 #define LLIST_DEFINED
2389 struct llist_struct
*next
;
2390 struct llist_struct
*prev
;
2398 struct nobug_context
2405 nobug_context (const char* file_
, int line_
, const char* func_
)
2406 : file(file_
), line(line_
), func(func_
) {}
2411 nobug_basename (const char* const file
);
2416 enum nobug_log_targets
2418 NOBUG_TARGET_RINGBUFFER
,
2419 NOBUG_TARGET_CONSOLE
,
2421 NOBUG_TARGET_SYSLOG
,
2422 NOBUG_TARGET_APPLICATION
2428 struct nobug_flag
* parent
;
2431 struct nobug_ringbuffer
* ringbuffer_target
;
2432 FILE* console_target
;
2437 nobug_env_parse_flag (const char* env
, struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
);
2440 nobug_env_init_flag (struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
);
2446 struct nobug_ringbuffer
2448 struct llist_struct node
; /* all ringbufers are chained together, needed for sync */
2456 enum nobug_ringbuffer_flags
2458 NOBUG_RINGBUFFER_DEFAULT
, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
2459 NOBUG_RINGBUFFER_APPEND
= 1, /* use existing backing file, append if possible */
2460 NOBUG_RINGBUFFER_TEMP
= 2, /* unlink file instantly */
2461 NOBUG_RINGBUFFER_KEEP
= 4 /* dont unlink the file at destroy */
2464 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
2465 with sane (but undefined) semantics.
2468 struct nobug_ringbuffer
*
2469 nobug_ringbuffer_init (struct nobug_ringbuffer
* self
, size_t size
,
2470 size_t guard
, const char * name
, int flags
);
2472 struct nobug_ringbuffer
*
2473 nobug_ringbuffer_new (size_t size
, size_t guard
, const char * name
, int flags
);
2475 struct nobug_ringbuffer
*
2476 nobug_ringbuffer_destroy (struct nobug_ringbuffer
* self
);
2479 nobug_ringbuffer_delete (struct nobug_ringbuffer
* self
);
2482 nobug_ringbuffer_sync (struct nobug_ringbuffer
* self
);
2485 nobug_ringbuffer_allsync (void);
2488 nobug_ringbuffer_vprintf (struct nobug_ringbuffer
* self
, const char* fmt
, va_list ap
);
2491 nobug_ringbuffer_printf (struct nobug_ringbuffer
* self
, const char* fmt
, ...);
2494 nobug_ringbuffer_append (struct nobug_ringbuffer
* self
);
2497 nobug_ringbuffer_extend (struct nobug_ringbuffer
* self
, size_t newsize
, const char fill
);
2500 nobug_ringbuffer_prev (struct nobug_ringbuffer
* self
, char* pos
);
2503 nobug_ringbuffer_next (struct nobug_ringbuffer
* self
, char* pos
);
2506 nobug_ringbuffer_save (struct nobug_ringbuffer
* self
, FILE* out
);
2509 nobug_ringbuffer_load (struct nobug_ringbuffer
* self
, FILE* in
);
2512 nobug_ringbuffer_pos (struct nobug_ringbuffer
* self
);
2515 nobug_ringbuffer_pop (struct nobug_ringbuffer
* self
);
2519 multithreading extras
2522 struct nobug_tls_data
2524 const char* thread_id
;
2525 unsigned thread_num
; /* thread counter at initialization, gives a unique thread number */
2526 unsigned thread_gen
; /* incremented at each name reset, (currently unused) */
2528 struct llist_struct res_stack
; /* resources of this thread */
2530 unsigned coverage_disable_cnt
;
2533 extern pthread_key_t nobug_tls_key
;
2535 struct nobug_tls_data
*
2536 nobug_thread_set (const char* name
);
2538 struct nobug_tls_data
*
2539 nobug_thread_get (void);
2542 nobug_thread_id_set (const char* name
);
2545 nobug_thread_id_get (void);
2547 #if NOBUG_USE_PTHREAD
2548 extern pthread_mutex_t nobug_logging_mutex
;
2549 extern pthread_mutex_t nobug_resource_mutex
;
2553 nobug_thread_data (void);
2558 enum nobug_resource_state
2560 NOBUG_RESOURCE_INVALID
,
2561 NOBUG_RESOURCE_WAITING
,
2562 NOBUG_RESOURCE_TRYING
,
2563 NOBUG_RESOURCE_EXCLUSIVE
,
2564 NOBUG_RESOURCE_RECURSIVE
,
2565 NOBUG_RESOURCE_SHARED
2569 struct nobug_resource_header
2571 struct llist_struct node
; /* link node for resource registry or users */
2572 const char* name
; /* name */
2573 struct nobug_context extra
; /* context information */
2576 struct nobug_resource_node
;
2577 struct nobug_resource_user
;
2579 struct nobug_resource_record
2581 struct nobug_resource_header hdr
;
2583 struct llist_struct users
; /* list of users of this resource */
2584 const void* object_id
; /* unique identifer, usually a this pointer or similar */
2585 const char* type
; /* type */
2587 #if NOBUG_USE_PTHREAD
2588 struct llist_struct nodes
;
2593 struct nobug_resource_node
2595 struct llist_struct node
; /* all nodes for one resource */
2597 struct nobug_resource_record
* resource
; /* backpointer */
2598 struct nobug_resource_node
* parent
; /* upwards the tree */
2600 struct llist_struct childs
; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2601 struct llist_struct cldnode
; /* node to accumulate all childrens of a parent (TODO slist) */
2605 struct nobug_resource_user
2607 struct nobug_resource_header hdr
;
2609 struct nobug_resource_node
* current
; /* this resource */
2610 enum nobug_resource_state state
; /* state */
2612 #if NOBUG_USE_PTHREAD
2613 struct nobug_tls_data
* thread
; /* pointer to this theads id */
2614 struct llist_struct res_stack
; /* resources of this thread */
2619 extern const char* nobug_resource_error
;
2621 extern const char* nobug_resource_states
[];
2625 nobug_resource_init (void);
2628 nobug_resource_destroy (void);
2631 struct nobug_resource_record
*
2632 nobug_resource_announce (const char* type
, const char* name
, const void* object_id
, const struct nobug_context extra
);
2635 nobug_resource_announce_complete (void);
2638 nobug_resource_forget (struct nobug_resource_record
* node
);
2641 struct nobug_resource_user
*
2642 nobug_resource_enter (struct nobug_resource_record
* resource
,
2644 enum nobug_resource_state state
,
2645 const struct nobug_context extra
);
2649 nobug_resource_leave (struct nobug_resource_user
* handle
);
2653 nobug_resource_leave_pre (void);
2657 nobug_resource_record_available (void);
2661 nobug_resource_user_available (void);
2664 #if NOBUG_USE_PTHREAD
2666 nobug_resource_node_available (void);
2671 nobug_resource_reset (struct nobug_resource_record
* self
);
2675 nobug_resource_resetall (void);
2678 struct nobug_resource_dump_context
2680 struct nobug_flag
* flag
;
2682 struct nobug_context ctx
;
2685 nobug_resource_dump_context (struct nobug_flag
* flag_
,
2687 struct nobug_context ctx_
)
2688 : flag(flag_
), level(level_
), ctx(ctx_
) {}
2692 enum nobug_resource_state
2693 nobug_resource_mystate (struct nobug_resource_record
* res
);
2696 nobug_resource_dump (struct nobug_resource_record
* resource
, const struct nobug_resource_dump_context context
);
2699 nobug_resource_dump_all (const struct nobug_resource_dump_context context
);
2702 nobug_resource_state (struct nobug_resource_user
* resource
,
2703 enum nobug_resource_state state
);
2707 nobug_resource_list (const struct nobug_resource_dump_context context
);
2711 global config, data and defaults
2713 void nobug_init (const struct nobug_context context
);
2716 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2717 (and destroying is global!) it is only provided for the nobug testsuite itself
2719 void nobug_destroy (const struct nobug_context context
);
2722 nobug_backtrace_glibc (const struct nobug_context context
);
2725 nobug_backtrace_valgrind (const struct nobug_context context
);
2728 nobug_log_begin (char* header
, struct nobug_flag
* flag
, const char* what
, const struct nobug_context ctx
);
2732 nobug_log_end (struct nobug_flag
* flag
, int lvl
);
2735 /* must be called inbetween log_begin and log_end */
2737 nobug_log_line (char** start
, char* header
, struct nobug_flag
* flag
, int lvl
, const char* fmt
, ...);
2741 nobug_log (struct nobug_flag
* flag
, int lvl
, const char* what
,
2742 const struct nobug_context ctx
,
2743 const char* fmt
, ...) NOBUG_ATTR_PRINTF(5, 6);
2746 extern struct nobug_ringbuffer nobug_default_ringbuffer
;
2747 extern FILE* nobug_default_file
;
2748 extern struct nobug_flag nobug_flag_NOBUG_ON
;
2749 extern struct nobug_flag nobug_flag_NOBUG_ANN
;
2750 extern struct nobug_flag nobug_flag_nobug
;
2751 extern unsigned long long nobug_counter
;
2753 //callbacks HEAD- Callbacks; callbacks; function hooks to catch nobug actions
2755 //callbacks NoBug provides callbacks, applications can use these
2756 //callbacks to present logging information in some custom way or hook some special processing in.
2757 //callbacks The callbacks are initialized to NULL and never modified by NoBug, it is the sole responsibility
2758 //callbacks of the user to manage them.
2760 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2761 //callbacks documented below which must be followed.
2763 //callbacks PARA logging callback prototype; logging_cb; type of a logging callback function
2765 typedef void (*nobug_logging_cb
)(const struct nobug_flag
* flag
, //callbacks VERBATIM;
2766 int priority
, //callbacks VERBATIM;
2767 const char *log
, //callbacks VERBATIM;
2768 void* data
); //callbacks VERBATIM;
2770 //callbacks `flag`::
2771 //callbacks Flag structure which defines the logging configuration for this event
2772 //callbacks `priority`::
2773 //callbacks Log level of the current event
2775 //callbacks Pointing to the current log line in the ringbuffer or `NULL`
2776 //callbacks `data`::
2777 //callbacks Global pointer defined by the user, passed arround (see below)
2780 //callbacks PARA abort callback prototype; abort_cb; type of a abort callback function
2782 typedef void (*nobug_abort_cb
)(void* data
); //callbacks VERBATIM;
2784 //callbacks `data`::
2785 //callbacks Global data defined by the user, passed arround (see below)
2788 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2791 void* nobug_callback_data
; //callbacks VERBATIM;
2793 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2794 //callbacks to pass extra data to the callback functions.
2797 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2800 nobug_logging_cb nobug_logging_callback
; //callbacks VERBATIM;
2802 //callbacks This callback gets called when something gets logged.
2803 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2804 //callbacks functions from here recursively will deadlock and must be avoided.
2805 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2806 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2807 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2809 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2810 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2811 //callbacks `log` parameter in xref:THREADDATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2812 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2813 //callbacks from this function.
2816 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2819 nobug_logging_cb nobug_postlogging_callback
; //callbacks VERBATIM;
2821 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2822 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2823 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2824 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREADDATA[NOBUG_THREAD_DATA] can be
2825 //callbacks retrieved here and may need to be cleaned up here.
2828 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2831 nobug_abort_cb nobug_abort_callback
; //callbacks VERBATIM;
2833 //callbacks This callback gets called when the application shall be terminated due an error.
2834 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2835 //callbacks is called.
2837 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2838 //callbacks throws an exception here, the application must shut down as soon as possible.
2839 //callbacks Most causes for aborts are optimitzed out in `RELEASE` builds.
2843 /* block statement macros for sections must not be left by a jump this function will assert this with a NOBUG_CLEANUP attribute */
2845 nobug_section_cleaned (int* self
)
2849 nobug_log (&nobug_flag_NOBUG_ON
,
2850 LOG_EMERG
, "RESOURCE_SECTION",
2852 "illegal leaving of resource section (goto, return, ..)");
2859 fault coverage checking
2862 struct nobug_coverage_record
2865 char state
; /* 'F' from FAILURE or 'P' from PASS */
2868 extern void* nobug_coverage_tree
;
2871 nobug_coverage_parse_log (FILE* log
);
2873 struct nobug_coverage_record
2874 nobug_coverage_check (void);
2877 nobug_coverage_init (const struct nobug_context context
);
2885 #ifndef NOBUG_LIBNOBUG_C
2888 tag this translation unit as unchecked in ALPHA and BETA builds
2890 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED
;)
2893 /* some configuration when compiling nobug */
2894 /* Maximal length of a log line header (silently truncated if exceed) */
2895 #define NOBUG_MAX_LOG_HEADER_SIZE 128
2896 /* Maximal linebreaks in a single logging instruction which get translated to multiple lines */
2897 #define NOBUG_MAX_LOG_LINES 32
2899 #endif /* NOBUG_LIBNOBUG_C */