2 This file is part of the NoBug debugging library.
5 2006, 2007, 2008, 2009,
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 */
62 #ifdef HAVE_EXECINFO_H
63 # ifndef NOBUG_USE_EXECINFO
64 # define NOBUG_USE_EXECINFO 1
67 # undef NOBUG_USE_EXECINFO
68 # define NOBUG_USE_EXECINFO 0
71 #if NOBUG_USE_EXECINFO
75 #if defined(HAVE_VALGRIND) && !defined(NVALGRIND)
76 # ifndef NOBUG_USE_VALGRIND
77 # define NOBUG_USE_VALGRIND 1
80 # undef NOBUG_USE_VALGRIND
81 # define NOBUG_USE_VALGRIND 0
84 #if NOBUG_USE_VALGRIND
89 # ifndef NOBUG_USE_PTHREAD
90 # define NOBUG_USE_PTHREAD 1
93 # ifdef NOBUG_USE_PTHREAD
94 # undef NOBUG_USE_PTHREAD
96 # define NOBUG_USE_PTHREAD 0
104 //assertions HEAD- Assertions;;
106 //assertions PARA CHECK; CHECK; unnconditional assertion for testsuites
107 //assertions CHECK(expr, ...)
108 //assertions CHECK_IF(when, expr, ...)
110 //assertions This assertion is never optimized out. Its main purpose is for implementing
111 //assertions testsuites where one want to assert tests independent of the build level
114 #define NOBUG_CHECK(expr, ...) \
115 NOBUG_ASSERT_(expr, "CHECK", NOBUG_CONTEXT, ""__VA_ARGS__)
117 #define NOBUG_CHECK_IF(when, expr, ...) \
118 NOBUG_WHEN(when, NOBUG_CHECK(expr, ""__VA_ARGS__))
122 //assertions PARA REQUIRE; REQUIRE; preconditions (input parameters)
123 //assertions REQUIRE(expr, ...)
124 //assertions REQUIRE_IF(when, expr, ...)
125 //assertions NOBUG_REQUIRE_CTX(expr, context,...)
126 //assertions NOBUG_REQUIRE_IF_CTX(when, expr, context, ...)
128 //assertions Precondition (input) check. Use these macros to validate input a
129 //assertions function receives. The checks are enabled in *ALPHA* and *BETA* builds and
130 //assertions optimized out in *RELEASE* builds.
133 #define NOBUG_REQUIRE(expr, ...) \
134 NOBUG_REQUIRE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
136 #define NOBUG_REQUIRE_CTX(expr, context, ...) \
137 NOBUG_IF_NOT_RELEASE(NOBUG_ASSERT_(expr, "PRECONDITION", context, ""__VA_ARGS__))
140 #define NOBUG_REQUIRE_IF(when, expr, context,...) \
141 NOBUG_REQUIRE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
143 #define NOBUG_REQUIRE_IF_CTX(when, expr, context,...) \
144 NOBUG_IF_NOT_RELEASE ( \
145 NOBUG_WHEN(when, NOBUG_REQUIRE_CTX(expr, context, ""__VA_ARGS__)) \
150 //assertions PARA ENSURE; ENSURE; postconditions (computation outcomes)
151 //assertions ENSURE(expr, ...)
152 //assertions ENSURE_IF(when, expr, ...)
153 //assertions NOBUG_ENSURE_CTX(expr, context, ...)
154 //assertions NOBUG_ENSURE_IF_CTX(when, expr, context, ...)
156 //assertions Postcondition (progress/output) check. Use these macros to validate the
157 //assertions data a function produces (example: return value). `ENSURE` is enabled
158 //assertions unconditionally in *ALPHA* builds and optimized out in *BETA* builds for
159 //assertions scopes which are tagged as `CHECKED`.
161 //assertions The `ENSURE_IF` variants are enabled in *ALPHA* and *BETA* builds.
163 //assertions In *RELEASE* builds this checks are
164 //assertions always optimized out, scopes tagged as `UNCHECKED` are not permitted.
167 #define NOBUG_ENSURE(expr, ...) \
168 NOBUG_ENSURE_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
170 #define NOBUG_ENSURE_CTX(expr, context, ...) \
171 NOBUG_IF_ALPHA (NOBUG_ASSERT_(expr, "POSTCONDITION", \
172 context, ""__VA_ARGS__)) \
174 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
175 NOBUG_ASSERT_(expr, "POSTCONDITION", \
176 context, ""__VA_ARGS__) \
181 #define NOBUG_ENSURE_IF(when, expr, ...) \
182 NOBUG_ENSURE_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
184 #define NOBUG_ENSURE_IF_CTX(when, expr, context, ...) \
185 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ENSURE(expr, context, ""__VA_ARGS__)))
189 //assertions PARA ASSERT; ASSERT; generic assertion
190 //assertions ASSERT(expr, ...)
191 //assertions ASSERT_IF(when, expr, ...)
192 //assertions NOBUG_ASSERT_CTX(expr, context, ...)
193 //assertions NOBUG_ASSERT_IF_CTX(when, expr, context, ...)
195 //assertions Generic check. Use these macros when you want to validate something
196 //assertions which doesn't fall into one of the above categories. A example is when
197 //assertions a library function can return a unexpected result (scanf with syntax
198 //assertions error in the formatstring, when a constant/literal formatstring is
199 //assertions expected). The checks are enabled in *ALPHA* and *BETA* builds and
200 //assertions optimized out in *RELEASE* builds.
203 #define NOBUG_ASSERT(expr, ...) \
204 NOBUG_ASSERT_CTX(expr, NOBUG_CONTEXT, ""__VA_ARGS__)
206 #define NOBUG_ASSERT_CTX(expr, context, ...) \
207 NOBUG_IF_NOT_RELEASE( \
208 NOBUG_ASSERT_(expr, "ASSERTION", \
209 context, ""__VA_ARGS__) \
213 #define NOBUG_ASSERT_IF(when, expr, ...) \
214 NOBUG_ASSERT_IF_CTX(when, expr, NOBUG_CONTEXT, ""__VA_ARGS__)
216 #define NOBUG_ASSERT_IF_CTX(when, expr, context, ...) \
217 NOBUG_IF_NOT_RELEASE (NOBUG_WHEN(when, NOBUG_ASSERT_CTX(expr, context, ""__VA_ARGS__)))
221 //assertions PARA assert; assert; C standard assertion
222 //assertions assert(expr)
224 //assertions NoBug overrides the standard `assert` macro, using `NOBUG_ASSERT`.
225 //assertions This is just a compatibility feature, its use is not suggested.
229 #define assert(expr) NOBUG_ASSERT(expr)
236 #define NOBUG_ASSERT_(expr, what, context, fmt, ...) \
237 NOBUG_WHEN (!(expr), \
238 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
239 what, context, "(%s) " fmt, \
240 #expr, ## __VA_ARGS__); \
241 NOBUG_BACKTRACE_CTX(context); \
244 #else /* , ## __VA_ARGS__ eating the comma when the arglist is empty is a gcc extension, fallback for other compilers */
245 #define NOBUG_ASSERT_(expr, what, context, ...) \
246 NOBUG_WHEN (!(expr), \
247 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
250 NOBUG_BACKTRACE_CTX(context); \
256 //assertions PARA INVARIANT; INVARIANT; validate invariant state
257 //assertions INVARIANT(type, pointer, depth)
258 //assertions INVARIANT_IF(when,type, pointer, depth)
259 //assertions INVARIANT_ASSERT(expr, ...)
261 //assertions Checking invariants. You can provide more complex checking functions
262 //assertions which test the validity of datastructures. Invariants are only enabled
263 //assertions in *ALPHA* builds for scopes which are not tagged as `CHECKED` and
264 //assertions otherwise optimized out.
266 //assertions TODO: describe how to create invariant checks
268 // 'invariant_context' must be passed in
270 #define NOBUG_INVARIANT(type, pointer, depth) \
272 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
273 NOBUG_CAT(type,_invariant)(pointer, depth, \
279 #define NOBUG_INVARIANT_IF(when, type, pointer, depth) \
281 NOBUG_WHEN (NOBUG_SCOPE_UNCHECKED, \
283 NOBUG_CAT(type,_invariant)(pointer, depth, \
288 #define NOBUG_INVARIANT_ASSERT(expr, ...) \
289 NOBUG_ASSERT_(expr, "INVARIANT", invariant_context, ""__VA_ARGS__)
293 checked/unchecked tagged scopes
295 #define NOBUG_SCOPE_UNCHECKED NOBUG_CHECKED_VALUE == 0
297 #define NOBUG_CHECKED NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=1})
299 #define NOBUG_UNCHECKED \
300 NOBUG_IF_NOT_RELEASE(enum {NOBUG_CHECKED_VALUE=0}) \
301 NOBUG_IF_RELEASE(NOBUG_UNCHECKED_NOT_ALLOWED_IN_RELEASE_BUILD)
305 /*TODO dump-level for flags instead limits[0]*/
307 //dumpmacros PARA DUMP; DUMP; dumping datastructures
308 //dumpmacros DUMP(flag, type, pointer, depth)
309 //dumpmacros DUMP_IF(when, flag, type, pointer, depth)
311 //dumpmacros This macros call a datastructure dump of the object (`pointer`) in question.
312 //dumpmacros `DUMP` is only available in *ALPHA* and *BETA* builds, `DUMP_IF` is also
313 //dumpmacros enabled for the RELEASE builds.
316 #define NOBUG_DUMP(flag, type, pointer, depth) \
317 NOBUG_IF_NOT_RELEASE( \
318 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET], \
319 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT) \
323 #define NOBUG_DUMP_IF(when, flag, type, pointer, depth) \
324 NOBUG_WHEN (NOBUG_DUMP_LEVEL >= NOBUG_FLAG(flag).limits[NOBUG_LOG_TARGET] && when, \
325 NOBUG_CAT3 (nobug_, type, _dump)(pointer, depth, NOBUG_CONTEXT) \
330 //dumpmacros PARA DUMP_LOG; DUMP_LOG; logging helper for dumping
331 //dumpmacros DUMP_LOG(...)
332 //dumpmacros DUMP_LOG_IF(when, ...)
334 //dumpmacros Any output from `DUMP` handlers should be done by these macros.
336 //dumpmacros Dumping is by default done on level `LOG_DEBUG`, this can be overridden by
337 //dumpmacros defining `NOBUG_DUMP_LEVEL` to some other level.
339 // TODO document: 'dump_context' must be passed in
342 #define NOBUG_DUMP_LOG(...) \
343 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
344 "DUMP", dump_context, \
347 #define NOBUG_DUMP_LOG_IF(expr, ...) \
349 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_DUMP_LEVEL, \
350 "DUMP", dump_context, \
356 #ifndef NOBUG_DUMP_LEVEL
357 #define NOBUG_DUMP_LEVEL LOG_DEBUG
361 //logmacros HEAD- Logging Macros;;
363 //logmacros Logging targets a flag (except for `ECHO`) and is done at a log-level relating to syslog levels.
365 //logmacros NOTE: there is no logging macro for `LOG_EMERG`, this is only used by the assertions as fatal message
367 //logmacros PARA ECHO; ECHO; unconditional logging for tests
368 //logmacros ECHO(...)
370 //logmacros Never optimized out, logs at LOG_NOTICE level. Its main purpose is for implementing
371 //logmacros testsuites where one want to print and log messages independent of the build level
374 #define NOBUG_ECHO(...) \
375 NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_NOTICE, "ECHO", NOBUG_CONTEXT, ""__VA_ARGS__)
378 //logmacros PARA ALERT; ALERT; about to die
379 //logmacros ALERT(flag, ...)
380 //logmacros ALERT_IF(when, flag, ...)
381 //logmacros NOBUG_ALERT_CTX(flag, context, ...)
382 //logmacros NOBUG_ALERT_IF_CTX(when, flag, context, ...)
384 //logmacros This is the most critical condition an application might log. This might be used
385 //logmacros if an error occurs which can not be handled except a safe shutdown for example.
388 #define NOBUG_ALERT(flag, ...) \
389 NOBUG_ALERT_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
391 #define NOBUG_ALERT_IF(expr, flag, ...) \
392 NOBUG_ALERT_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
395 #define NOBUG_ALERT_CTX(flag, context, ...) \
396 NOBUG_LOG_CTX(flag, LOG_ALERT, context, ""__VA_ARGS__)
398 #define NOBUG_ALERT_IF_CTX(expr, flag, context, ...) \
399 NOBUG_LOG_IF(expr, flag, LOG_ALERT, context, ""__VA_ARGS__)
404 //logmacros PARA CRITICAL; CRITICAL; can not continue
405 //logmacros CRITICAL(flag, ...)
406 //logmacros CRITICAL_IF(when, flag, ...)
407 //logmacros NOBUG_CRITICAL_CTX(flag, context, ...)
408 //logmacros NOBUG_CRITICAL_IF_CTX(when, flag, context, ...)
410 //logmacros An error which can not be handled occured but the application does not need to be
411 //logmacros shutdowen, perhaps waiting for an operator to fix the cause.
414 #define NOBUG_CRITICAL(flag, ...) \
415 NOBUG_CRITICAL_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
417 #define NOBUG_CRITICAL_CTX(flag, context, ...) \
418 NOBUG_LOG_CTX(flag, LOG_CRIT, context, ""__VA_ARGS__)
421 #define NOBUG_CRITICAL_IF(expr, flag, ...) \
422 NOBUG_CRITICAL_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
424 #define NOBUG_CRITICAL_IF_CTX(expr, flag, context, ...) \
425 NOBUG_LOG_IF_CTX(expr, flag, LOG_CRIT, context, ""__VA_ARGS__)
429 //logmacros PARA ERROR; ERROR; something gone wrong
430 //logmacros ERROR(flag, ...)
431 //logmacros ERROR_IF(when, flag, ...)
432 //logmacros NOBUG_ERROR_CTX(flag, context, ...)
433 //logmacros NOBUG_ERROR_IF_CTX(when, flag, context, ...)
435 //logmacros Application takes a error handling brach
438 #define NOBUG_ERROR(flag, ...) \
439 NOBUG_ERROR_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
441 #define NOBUG_ERROR_CTX(flag, context, ...) \
442 NOBUG_LOG_CTX(flag, LOG_ERR, context, ""__VA_ARGS__)
445 #define NOBUG_ERROR_IF(expr, flag, ...) \
446 NOBUG_ERROR_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
448 #define NOBUG_ERROR_IF_CTX(expr, flag, context, ...) \
449 NOBUG_LOG_IF_CTX(expr, flag, LOG_ERR, context, ""__VA_ARGS__)
453 //logmacros PARA WARN; WARN; unexpected fixable error
454 //logmacros WARN(flag, ...)
455 //logmacros WARN_IF(when, flag, ...)
456 //logmacros NOBUG_WARN_CTX(flag, context, ...)
457 //logmacros NOBUG_WARN_IF_CTX(when, flag, context, ...)
459 //logmacros Rare, handled but unexpected branch
462 #define NOBUG_WARN(flag, ...) \
463 NOBUG_WARN_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
465 #define NOBUG_WARN_CTX(flag, context, ...) \
466 NOBUG_LOG_CTX(flag, LOG_WARNING, context, ""__VA_ARGS__)
469 #define NOBUG_WARN_IF(expr, flag, ...) \
470 NOBUG_WARN_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
472 #define NOBUG_WARN_IF_CTX(expr, flag, context, ...) \
473 NOBUG_LOG_IF_CTX(expr, flag, LOG_WARNING, context, ""__VA_ARGS__)
477 //logmacros PARA INFO; INFO; progress message
478 //logmacros INFO(flag, ...)
479 //logmacros INFO_IF(when, flag, ...)
480 //logmacros NOBUG_INFO_CTX(flag, context, ...)
481 //logmacros NOBUG_INFO_IF_CTX(when, flag, context, ...)
483 //logmacros Message about program progress
486 #define NOBUG_INFO(flag, ...) \
487 NOBUG_INFO_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
489 #define NOBUG_INFO_CTX(flag, context, ...) \
490 NOBUG_LOG_CTX(flag, LOG_INFO, context, ""__VA_ARGS__)
493 #define NOBUG_INFO_IF(expr, flag, ...) \
494 NOBUG_INFO_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
496 #define NOBUG_INFO_IF_CTX(expr, flag, context, ...) \
497 NOBUG_LOG_IF_CTX(expr, flag, LOG_INFO, context, ""__VA_ARGS__)
501 //logmacros PARA NOTICE; NOTICE; detailed progress message
502 //logmacros NOTICE(flag, ...)
503 //logmacros NOTICE_IF(when, flag, ...)
504 //logmacros NOBUG_NOTICE_CTX(flag, context, ...)
505 //logmacros NOBUG_NOTICE_IF_CTX(when, flag, context, ...)
507 //logmacros More detailed progress message
510 #define NOBUG_NOTICE(flag, ...) \
511 NOBUG_NOTICE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
513 #define NOBUG_NOTICE_CTX(flag, context, ...) \
514 NOBUG_LOG_CTX(flag, LOG_NOTICE, context, ""__VA_ARGS__)
517 #define NOBUG_NOTICE_IF(expr, flag, ...) \
518 NOBUG_NOTICE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
520 #define NOBUG_NOTICE_IF_CTX(expr, flag, context, ...) \
521 NOBUG_LOG_IF_CTX(expr, flag, LOG_NOTICE, context, ""__VA_ARGS__)
524 //logmacros PARA TRACE; TRACE; debugging level message
525 //logmacros TRACE(flag, ...)
526 //logmacros TRACE_IF(when, flag, ...)
527 //logmacros NOBUG_TRACE_CTX(flag, context, ...)
528 //logmacros NOBUG_TRACE_IF_CTX(when, flag, context, ...)
530 //logmacros Very fine grained messages
532 //logmacros NOTE: that `TRACE` corresponds to `LOG_DEBUG`, because using `DEBUG` could be ambiguous.
535 #define NOBUG_TRACE(flag, ...) \
536 NOBUG_TRACE_CTX(flag, NOBUG_CONTEXT, ""__VA_ARGS__)
538 #define NOBUG_TRACE_CTX(flag, context, ...) \
539 NOBUG_LOG_CTX(flag, LOG_DEBUG, context, ""__VA_ARGS__)
542 #define NOBUG_TRACE_IF(expr, flag, ...) \
543 NOBUG_TRACE_IF_CTX(expr, flag, NOBUG_CONTEXT, ""__VA_ARGS__)
545 #define NOBUG_TRACE_IF_CTX(expr, flag, context, ...) \
546 NOBUG_LOG_IF_CTX(expr, flag, LOG_DEBUG, context, ""__VA_ARGS__)
550 //logmacros PARA LOG; LOG; generic logging
551 //logmacros NOBUG_LOG_CTX(flag, lvl, context, ...)
552 //logmacros NOBUG_LOG_IF_CTX(when, flag, lvl, context, ...)
554 //logmacros Generic logging macro which takes the level explicitly,
555 //logmacros avoid this, unless you implement your own logging facilities.
558 #define NOBUG_LOG_CTX(flag, lvl, context, ...) \
559 NOBUG_LOG_(&NOBUG_FLAG(flag), lvl, NOBUG_LVL(lvl), context, ""__VA_ARGS__)
562 #define NOBUG_LOG_IF_CTX(expr, flag, lvl, context, ...) \
564 NOBUG_LOG_CTX(flag, lvl, context, ""__VA_ARGS__) \
569 low level logging handler
571 Note: all fmt concatenations use an empty string ""__VA_ARG__
572 except this one which must use a single space " " before __VA_ARGS__ for formatting the log message correctly (and silence a gcc warning)
574 #define NOBUG_LOG_(flag, lvl, what, context, ...) \
575 NOBUG_WHEN (lvl <= NOBUG_LOG_BASELIMIT && lvl <= (flag)->limits[NOBUG_TARGET_RINGBUFFER], \
576 nobug_log (flag, lvl, what, context, " "__VA_ARGS__) \
580 #define NOBUG_LVL(lvl) NOBUG_LVL_##lvl
581 #define NOBUG_LVL_0 "EMERG"
582 #define NOBUG_LVL_1 "ALERT"
583 #define NOBUG_LVL_2 "CRIT"
584 #define NOBUG_LVL_3 "ERR"
585 #define NOBUG_LVL_4 "WARNING"
586 #define NOBUG_LVL_5 "NOTICE"
587 #define NOBUG_LVL_6 "INFO"
588 #define NOBUG_LVL_7 "TRACE"
591 //logmacros PARA LOG_BASELIMIT; LOG_BASELIMIT; minimum compliled-in logging limit
592 //logmacros NOBUG_LOG_BASELIMIT_ALPHA
593 //logmacros NOBUG_LOG_BASELIMIT_BETA
594 //logmacros NOBUG_LOG_BASELIMIT_RELEASE
595 //logmacros NOBUG_LOG_BASELIMIT
597 //logmacros anything more detailed than this base limits will be optimized out.
598 //logmacros This is used to reduce the logging overhead for *RELEASE* builds.
599 //logmacros By default the limit is set to `LOG_DEBUG` for *ALPHA* and *BETA*
600 //logmacros builds, so all logging is retained and `LOG_NOTICE` in *RELEASE*
601 //logmacros builds to log the application progress only coarsely then.
603 //logmacros This macros can be defined before including 'nobug.h' to some other
604 //logmacros log level (as defined in 'syslog.h').
607 #ifndef NOBUG_LOG_BASELIMIT_ALPHA
608 #define NOBUG_LOG_BASELIMIT_ALPHA LOG_DEBUG
611 #ifndef NOBUG_LOG_BASELIMIT_BETA
612 #define NOBUG_LOG_BASELIMIT_BETA LOG_DEBUG
615 #ifndef NOBUG_LOG_BASELIMIT_RELEASE
616 #define NOBUG_LOG_BASELIMIT_RELEASE LOG_NOTICE
619 #ifndef NOBUG_LOG_BASELIMIT
620 #define NOBUG_LOG_BASELIMIT \
621 NOBUG_IF_ALPHA(NOBUG_LOG_BASELIMIT_ALPHA) \
622 NOBUG_IF_BETA(NOBUG_LOG_BASELIMIT_BETA) \
623 NOBUG_IF_RELEASE(NOBUG_LOG_BASELIMIT_RELEASE)
627 //srccontext HEAD~ Source Contexts; NOBUG_CONTEXT; pass information about the source location
628 //srccontext NOBUG_CONTEXT
629 //srccontext NOBUG_CONTEXT_NOFUNC
631 //srccontext NoBug passes information about the source location of a given statement in
632 //srccontext `const struct nobug_context` structures. These can be generated with
633 //srccontext `NOBUG_CONTEXT` or `NOBUG_CONTEXT_NOFUNC`. The later one doesn't define a
634 //srccontext function name and must be used when the function context is not available
635 //srccontext like in static initialization etc..
639 #define NOBUG_CONTEXT ((const struct nobug_context){__FILE__, __LINE__, __func__})
641 #define NOBUG_CONTEXT_NOFUNC ((const struct nobug_context){__FILE__, __LINE__, "NOFUNC"})
643 #define NOBUG_CONTEXT_NIL ((const struct nobug_context){"NIL", 0, "NIL"})
647 //annotations HEAD- Source Annotations;;
649 //annotations One can tag features as:
655 DEPRECATED log nothing wont compile
657 //annotations PARA DEPRECATED; DEPRECATED; to be discarded in future
658 //annotations DEPRECATED(...)
660 //annotations Something which shouldn't be used in future
663 #define NOBUG_DEPRECATED(...) \
664 NOBUG_IF_ALPHA(NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_WARN, \
665 "DEPRECATED", NOBUG_CONTEXT, ""__VA_ARGS__) \
667 NOBUG_IF_RELEASE(NOBUG_DEPRECATED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
672 UNIMPLEMENTED abort abort wont compile
674 //annotations PARA UNIMPLEMENTED; UNIMPLEMENTED; not yet implemented
675 //annotations UNIMPLEMENTED(...)
677 //annotations not yet finished feature
680 #define NOBUG_UNIMPLEMENTED(...) \
681 NOBUG_IF_NOT_RELEASE ( do { \
682 NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_EMERG, \
683 "UNIMPLEMENTED", NOBUG_CONTEXT, ""__VA_ARGS__); \
686 NOBUG_IF_RELEASE( NOBUG_UNIMPLEMENTED_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
691 FIXME log wont compile wont compile
693 //annotations PARA FIXME; FIXME; known bug
694 //annotations FIXME(...)
696 //annotations known bug to be fixed later
699 #define NOBUG_FIXME(...) \
700 NOBUG_IF_ALPHA( NOBUG_ONCE( NOBUG_LOG_(&nobug_flag_NOBUG_ANN, LOG_ALERT, \
701 "FIXME", NOBUG_CONTEXT, ""__VA_ARGS__))) \
702 NOBUG_IF_BETA( NOBUG_FIXME_NOT_ALLOWED_IN_BETA_BUILD(__VA_ARGS__)) \
703 NOBUG_IF_RELEASE( NOBUG_FIXME_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
708 TODO log log wont compile
710 //annotations PARA TODO; TODO; things to be done
711 //annotations TODO(...)
713 //annotations enhancement to be done soon
716 #define NOBUG_TODO(...) \
717 NOBUG_IF_NOT_RELEASE ( \
719 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_NOTICE, \
720 "TODO", NOBUG_CONTEXT, ""__VA_ARGS__); \
722 NOBUG_IF_RELEASE(NOBUG_TODO_NOT_ALLOWED_IN_RELEASE_BUILD(__VA_ARGS__))
727 PLANNED log nothing nothing
729 //annotations PARA PLANNED; PLANNED; ideas for future
730 //annotations PLANNED(...)
732 //annotations future enhancement
735 #define NOBUG_PLANNED(...) \
736 NOBUG_IF_ALPHA( NOBUG_ONCE(NOBUG_LOG_ (&nobug_flag_NOBUG_ANN, LOG_INFO, \
737 "PLANNED", NOBUG_CONTEXT, ""__VA_ARGS__)))
742 NOTREACHED abort abort nothing
744 //annotations PARA NOTREACHED; NOTREACHED; code path never taken
745 //annotations NOTREACHED(...)
747 //annotations used to tag code-path which shall be never executed.
750 #define NOBUG_NOTREACHED(...) \
751 NOBUG_IF_NOT_RELEASE( do { \
752 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
753 "NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
759 //annotations PARA ELSE_NOTREACHED; ELSE_NOTREACHED; alternative never taken
760 //annotations ELSE_NOTREACHED(...)
762 //annotations same as `else NOTREACHED()`, but wholly optimized out in release builds.
765 #define NOBUG_ELSE_NOTREACHED(...) \
766 NOBUG_IF_NOT_RELEASE( else do { \
767 NOBUG_LOG_( &nobug_flag_NOBUG_ANN, LOG_EMERG, \
768 "ELSE_NOTREACHED", NOBUG_CONTEXT, ""__VA_ARGS__); \
774 //faultinjection HEAD- Fault injection;;
776 //faultinjection NoBug has some macros which can be used to simulate errorneous behaviour:
778 //faultinjection PARA INJECT_GOODBAD; INJECT_GOODBAD; fault injection expression
779 //faultinjection INJECT_GOODBAD(expr, good, bad)
781 //faultinjection substitutes to an expression and returns good when expr is false and
782 //faultinjection bad when expr is true. In BETA and RELEASE builds 'good' is always returned.
785 #define NOBUG_INJECT_GOODBAD(expr, good, bad) \
786 NOBUG_IF_ALPHA((expr)?({NOBUG_INJECT_LOG(#expr": "#bad);bad;}):good) \
787 NOBUG_IF_NOT_ALPHA(good)
791 //faultinjection PARA INJECT_FAULT; INJECT_FAULT; fault injection statement
792 //faultinjection INJECT_FAULT(expr, bad)
794 //faultinjection substitutes to a statement which executes 'bad'
795 //faultinjection when expr is true. Optimitzed out in BETA and RELEASE builds.
798 #define NOBUG_INJECT_FAULT(expr, bad) \
799 NOBUG_IF_ALPHA(NOBUG_WHEN(expr,NOBUG_INJECT_LOG(#expr": "#bad); bad))
803 //faultinjection PARA INJECT_LEVEL; INJECT_LEVEL; log level for fault injection
804 //faultinjection In both cases, when a fault is injected it will be logged at
805 //faultinjection `NOBUG_INJECT_LEVEL` (default: `LOG_NOTICE`). This can be defined
806 //faultinjection before including 'nobug.h' to override it.
809 #define NOBUG_INJECT_LOG(msg) \
810 NOBUG_LOG_( &nobug_flag_NOBUG_ON, NOBUG_INJECT_LEVEL, \
811 "INJECT_FAULT", NOBUG_CONTEXT, \
815 #ifndef NOBUG_INJECT_LEVEL
816 #define NOBUG_INJECT_LEVEL LOG_NOTICE
823 #define NOBUG_FLAG(name) NOBUG_CAT(nobug_flag_, name)
825 #define NOBUG_DECLARE_FLAG(name) extern struct nobug_flag NOBUG_FLAG(name)
828 #define NOBUG_DEFINE_FLAG(name) \
829 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
830 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
831 struct nobug_flag NOBUG_FLAG(name) = \
832 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
833 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
834 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
835 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
836 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
837 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
841 #define NOBUG_DEFINE_FLAG_PARENT(name, parent) \
842 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
843 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
844 NOBUG_DECLARE_FLAG(parent); \
845 struct nobug_flag NOBUG_FLAG(name) = \
846 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
847 {LOG_DEBUG, LOG_INFO, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
848 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
849 {LOG_INFO, LOG_NOTICE, LOG_NOTICE, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
850 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
851 {LOG_NOTICE, -1, LOG_WARNING, LOG_WARNING, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
855 #define NOBUG_DEFINE_FLAG_LIMIT(name, limit) \
856 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
857 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
858 struct nobug_flag NOBUG_FLAG(name) = \
859 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, NULL, 0, \
860 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
861 NOBUG_IF(NOBUG_MODE_BETA, {#name, NULL, 0, \
862 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
863 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, NULL, 0, \
864 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
868 #define NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, limit) \
869 NOBUG_FLAG_IF_DECLAREONLY(NOBUG_DECLARE_FLAG(name)) \
870 NOBUG_FLAG_IF_NOT_DECLAREONLY( \
871 NOBUG_DECLARE_FLAG(parent); \
872 struct nobug_flag NOBUG_FLAG(name) = \
873 NOBUG_IF(NOBUG_MODE_ALPHA, {#name, &NOBUG_FLAG(parent), 0, \
874 {LOG_DEBUG, limit, LOG_DEBUG, -1, LOG_INFO}, &nobug_default_ringbuffer, NULL,NULL}) \
875 NOBUG_IF(NOBUG_MODE_BETA, {#name, &NOBUG_FLAG(parent), 0, \
876 {LOG_INFO, LOG_NOTICE, limit, LOG_NOTICE, LOG_WARNING}, &nobug_default_ringbuffer, NULL,NULL}) \
877 NOBUG_IF(NOBUG_MODE_RELEASE, {#name, &NOBUG_FLAG(parent), 0, \
878 {LOG_NOTICE, -1, LOG_WARNING, limit, LOG_ERR}, &nobug_default_ringbuffer, NULL,NULL}) \
882 #define NOBUG_INIT_FLAG(name) \
883 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, NOBUG_LOG_LIMIT, NOBUG_CONTEXT_NOFUNC)
886 #define NOBUG_INIT_FLAG_LIMIT(name, default) \
887 nobug_env_init_flag (&NOBUG_FLAG(name), NOBUG_LOG_TARGET, default, NOBUG_CONTEXT_NOFUNC)
890 #define NOBUG_CPP_DEFINE_FLAG(name) \
891 NOBUG_FLAG_IF_DECLAREONLY( \
892 NOBUG_DECLARE_FLAG(name); \
893 extern int nobug_cppflag_##name \
895 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
896 NOBUG_DEFINE_FLAG(name); \
897 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
901 #define NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent) \
902 NOBUG_FLAG_IF_DECLAREONLY( \
903 NOBUG_DECLARE_FLAG(name); \
904 extern int nobug_cppflag_##name \
906 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
907 NOBUG_DEFINE_FLAG_PARENT(name, parent); \
908 int nobug_cppflag_##name = NOBUG_INIT_FLAG(name) \
912 #define NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default) \
913 NOBUG_FLAG_IF_DECLAREONLY( \
914 NOBUG_DECLARE_FLAG(name); \
915 extern int nobug_cppflag_##name \
917 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
918 NOBUG_DEFINE_FLAG_LIMIT(name, default); \
919 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
923 #define NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default) \
924 NOBUG_FLAG_IF_DECLAREONLY( \
925 NOBUG_DECLARE_FLAG(name); \
926 extern int nobug_cppflag_##name \
928 NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP( \
929 NOBUG_DEFINE_FLAG_PARENT_LIMIT(name, parent, default); \
930 int nobug_cppflag_##name = NOBUG_INIT_FLAG_LIMIT(name, default) \
934 #ifndef NOBUG_DECLARE_ONLY
935 #define NOBUG_DECLARE_ONLY 0
938 #define NOBUG_FLAG_IF_DECLAREONLY(...) \
939 NOBUG_IF(NOBUG_DECLARE_ONLY, __VA_ARGS__)
941 #define NOBUG_FLAG_IF_NOT_DECLAREONLY(...) \
942 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
945 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
946 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, __VA_ARGS__)
948 #define NOBUG_FLAG_IF_NOT_DECLAREONLY_CPP(...) \
949 NOBUG_IFNOT(NOBUG_DECLARE_ONLY, NOBUG_ERROR_CANT_DEFINE_AUTOINITIALIZED_CPP_FLAGS_IN_C)
952 #ifndef NOBUG_LOG_LIMIT_ALPHA
953 # define NOBUG_LOG_LIMIT_ALPHA LOG_INFO
955 #ifndef NOBUG_LOG_LIMIT_BETA
956 # define NOBUG_LOG_LIMIT_BETA LOG_WARNING
958 #ifndef NOBUG_LOG_LIMIT_RELEASE
959 # define NOBUG_LOG_LIMIT_RELEASE LOG_CRIT
962 #ifndef NOBUG_LOG_LIMIT
963 # define NOBUG_LOG_LIMIT \
964 NOBUG_IF_ALPHA( NOBUG_LOG_LIMIT_ALPHA) \
965 NOBUG_IF_BETA( NOBUG_LOG_LIMIT_BETA) \
966 NOBUG_IF_RELEASE( NOBUG_LOG_LIMIT_RELEASE)
969 #ifndef NOBUG_LOG_TARGET_ALPHA
970 # define NOBUG_LOG_TARGET_ALPHA NOBUG_TARGET_CONSOLE
972 #ifndef NOBUG_LOG_TARGET_BETA
973 # define NOBUG_LOG_TARGET_BETA NOBUG_TARGET_FILE
975 #ifndef NOBUG_LOG_TARGET_RELEASE
976 # define NOBUG_LOG_TARGET_RELEASE NOBUG_TARGET_SYSLOG
979 #ifndef NOBUG_LOG_TARGET
980 # define NOBUG_LOG_TARGET \
981 NOBUG_IF_ALPHA( NOBUG_LOG_TARGET_ALPHA) \
982 NOBUG_IF_BETA( NOBUG_LOG_TARGET_BETA) \
983 NOBUG_IF_RELEASE( NOBUG_LOG_TARGET_RELEASE)
986 #define NOBUG_SET_LIMIT(flag, min) \
987 NOBUG_IF_NOT_RELEASE( NOBUG_FLAG(flag) = (min))
991 //resourcemacros HEAD~ Resource tracking macros;;
993 //resourcemacros INDEX RESOURCE_LOGGING; RESOURCE_LOGGING; switch resource logging on and off
994 //resourcemacros INDEX RESOURCE_LOG_LEVEL; RESOURCE_LOG_LEVEL; select the log level for resource logging
996 //resourcemacros Unless the user defines `NOBUG_RESOURCE_LOGGING` to 0 each of the above macros
997 //resourcemacros will emit a log message at `NOBUG_RESOURCE_LOG_LEVEL` which defaults to
998 //resourcemacros `LOG_DEBUG`.
1001 #ifndef NOBUG_RESOURCE_LOGGING
1002 #define NOBUG_RESOURCE_LOGGING 1
1005 #ifndef NOBUG_RESOURCE_LOG_LEVEL
1006 #define NOBUG_RESOURCE_LOG_LEVEL LOG_DEBUG
1011 //resourcemacros PARA RESOURCE_HANDLE; RESOURCE_HANDLE; define resource handles
1012 //resourcemacros RESOURCE_HANDLE(name)
1013 //resourcemacros RESOURCE_HANDLE_INIT(name)
1014 //resourcemacros RESOURCE_USER(name)
1015 //resourcemacros RESOURCE_USER_INIT(name)
1017 //resourcemacros Define and initialize handles for to track resources.
1019 //resourcemacros `name`::
1020 //resourcemacros identifer to be used for the handle
1022 //resourcemacros There are two kinds of handles, each resource itself is abstracted with a
1023 //resourcemacros `RESOURCE_HANDLE` and every access to this resources is tracked through a
1024 //resourcemacros `RESOURCE_USER` handle. These macros takes care that the declaration is optimized
1025 //resourcemacros out in the same manner as the rest of the resource tracker would be disabled.
1026 //resourcemacros You can still instantiate handles as `struct nobug_resource_record*` or
1027 //resourcemacros `struct nobug_resource_user*` in structures which must have a constant size
1028 //resourcemacros unconditional of the build level. The two `*_INIT` macros can be used to initialize
1029 //resourcemacros resource handles and are optimized out when the resource tracker gets disabled.
1032 #define NOBUG_RESOURCE_HANDLE(handle) \
1033 NOBUG_IF_ALPHA(struct nobug_resource_record* handle)
1035 #define NOBUG_RESOURCE_HANDLE_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1037 #define NOBUG_RESOURCE_USER(handle) \
1038 NOBUG_IF_ALPHA(struct nobug_resource_user* handle)
1040 #define NOBUG_RESOURCE_USER_INIT(handle) NOBUG_IF_ALPHA(handle = NULL)
1044 //resourcemacros PARA RESOURCE_ANNOUNCE; RESOURCE_ANNOUNCE; publish new resources
1045 //resourcemacros RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
1046 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW(flagptr, type, name, ptr, handle)
1047 //resourcemacros NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flagptr, type, name, ptr, handle, context)
1049 //resourcemacros Publishes resources.
1051 //resourcemacros `flag`::
1052 //resourcemacros the NoBug flag name which turns logging on for this macro
1053 //resourcemacros `type`::
1054 //resourcemacros a string which should denote the domain of the resource,
1055 //resourcemacros examples are "file", "mutex", "lock", "database" and so on
1056 //resourcemacros `name`::
1057 //resourcemacros the actual name of a named resource this as string which
1058 //resourcemacros together with type forms a unique identifier of the resource. `type` and
1059 //resourcemacros `name` must be available through the entire lifetime of the resource, using
1060 //resourcemacros literal strings is recommended
1061 //resourcemacros `identifier`::
1062 //resourcemacros a pointer which should be unique for this resource, any
1063 //resourcemacros kind of pointer will suffice, it is only used for identification. In
1064 //resourcemacros multithreaded applications the thread identifier becomes an additional
1065 //resourcemacros identifier
1066 //resourcemacros `handle`::
1067 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to point to
1068 //resourcemacros the newly created resource.
1070 //resourcemacros Resources must be unique, it is a fatal error when a resource it tried to be
1071 //resourcemacros announced more than one time.
1074 #define NOBUG_RESOURCE_ANNOUNCE(flag, type, name, ptr, handle) \
1075 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(&NOBUG_FLAG(flag), type, name, ptr, handle, NOBUG_CONTEXT)
1077 #define NOBUG_RESOURCE_ANNOUNCE_RAW(flag, type, name, ptr, handle) \
1078 NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, NOBUG_CONTEXT)
1080 #define NOBUG_RESOURCE_ANNOUNCE_RAW_CTX(flag, type, name, ptr, handle, context) \
1081 NOBUG_IF_ALPHA( do { \
1082 NOBUG_RESOURCE_LOCK; \
1083 NOBUG_REQUIRE_CTX(!handle, context, "Announced resource handle not initialized"); \
1084 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1085 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1086 "RESOURCE_ANNOUNCE", context, \
1087 "%s: %s@%p", type, name, ptr);) \
1088 NOBUG_RESOURCE_ASSERT_CTX(handle = nobug_resource_announce (type, name, ptr, \
1090 "RESOURCE_ASSERT_ANNOUNCE", context, \
1091 "%s: %s@%p %s", type, name, ptr, nobug_resource_error); \
1092 NOBUG_RESOURCE_UNLOCK; \
1097 //resourcemacros PARA RESOURCE_FORGET; RESOURCE_FORGET; remove resources
1098 //resourcemacros RESOURCE_FORGET(flag, handle)
1099 //resourcemacros NOBUG_RESOURCE_FORGET_RAW(flagptr, handle)
1100 //resourcemacros NOBUG_RESOURCE_FORGET_RAW_CTX(flagptr, handle, context)
1102 //resourcemacros Removes resources that have become unavailable from the registry.
1104 //resourcemacros `flag`::
1105 //resourcemacros the NoBug flag which turns logging on for this macro
1106 //resourcemacros `handle`::
1107 //resourcemacros the `NOBUG_RESOURCE_HANDLE` used to track this resource
1109 //resourcemacros The resource must still exist and no users must be attached to it, else a fatal
1110 //resourcemacros error is raised.
1113 #define NOBUG_RESOURCE_FORGET(flag, handle) \
1114 NOBUG_RESOURCE_FORGET_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1116 #define NOBUG_RESOURCE_FORGET_RAW(flag, handle) \
1117 NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1119 #define NOBUG_RESOURCE_FORGET_RAW_CTX(flag, handle, context) \
1120 NOBUG_IF_ALPHA( do { \
1121 NOBUG_RESOURCE_LOCK; \
1122 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1123 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1124 "RESOURCE_FORGET", context, "%s: %s@%p", \
1125 (handle)?(handle)->type:"", \
1126 (handle)?(handle)->hdr.name:"", \
1127 (handle)?(handle)->object_id:NULL);) \
1128 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_forget (handle), \
1129 "RESOURCE_ASSERT_FORGET", context, "%s: %s@%p: %s", \
1130 (handle)?(handle)->type:"", \
1131 (handle)?(handle)->hdr.name:"", \
1132 (handle)?(handle)->object_id:NULL, \
1133 nobug_resource_error); \
1135 NOBUG_RESOURCE_UNLOCK; \
1140 //resourcemacros PARA RESOURCE_ENTER; RESOURCE_ENTER; claim a resource
1141 //resourcemacros RESOURCE_ENTER(flag, announced, user, state, handle)
1142 //resourcemacros NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context)
1144 //resourcemacros Acquire a resource.
1146 //resourcemacros `flag`::
1147 //resourcemacros nobug flag which turns logging on for this macro
1148 //resourcemacros `announced`::
1149 //resourcemacros the handle set by `RESOURCE_ANNOUNCE`
1150 //resourcemacros `user`::
1151 //resourcemacros a free-form identifier
1152 //resourcemacros `state`::
1153 //resourcemacros the initial state, one of `NOBUG_RESOURCE_WAITING`, `NOBUG_RESOURCE_TRYING`,
1154 //resourcemacros `NOBUG_RESOURCE_EXCLUSIVE`, `NOBUG_RESOURCE_RECURSIVE` or `NOBUG_RESOURCE_SHARED`
1155 //resourcemacros `handle`::
1156 //resourcemacros a `NOBUG_RESOURCE_HANDLE` which will be initialized to the
1157 //resourcemacros entering node
1160 #define NOBUG_RESOURCE_ENTER(flag, resource, user, state, handle) \
1161 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, NOBUG_CONTEXT)
1163 #define NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, state, handle, context) \
1166 NOBUG_REQUIRE_CTX(resource, context, "Announced resource handle not initialized"); \
1167 NOBUG_REQUIRE_CTX(!(handle), context, "Resource handle already entered"); \
1168 NOBUG_RESOURCE_LOCK; \
1169 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1170 NOBUG_LOG_(&NOBUG_FLAG(flag), NOBUG_RESOURCE_LOG_LEVEL, \
1171 "RESOURCE_ENTER", context, \
1172 "%s: %s@%p: %s: %s", \
1173 (resource)?(resource)->type:"", \
1174 (resource)?(resource)->hdr.name:"", \
1175 (resource)?(resource)->object_id:NULL, \
1177 nobug_resource_states[state]);) \
1178 NOBUG_RESOURCE_ASSERT_CTX(handle = \
1179 nobug_resource_enter (resource, \
1182 "RESOURCE_ASSERT_ENTER", context, \
1183 "%s: %s@%p: %s: %s: %s", \
1184 (resource)?(resource)->type:"", \
1185 (resource)?(resource)->hdr.name:"", \
1186 (resource)?(resource)->object_id:NULL, \
1187 user, nobug_resource_states[state], \
1188 nobug_resource_error); \
1189 NOBUG_RESOURCE_UNLOCK; \
1193 //resourcemacros PARA RESOURCE_WAIT; RESOURCE_WAIT; wait for a resource to become available
1194 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle)
1195 //resourcemacros NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context)
1197 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1199 //resourcemacros .How to use it
1200 //resourcemacros [source,c]
1201 //resourcemacros ----
1202 //resourcemacros RESOURCE_WAIT(flag, resource, user, handle);
1203 //resourcemacros if (lock_my_resource() == ERROR)
1204 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle);
1205 //resourcemacros else
1206 //resourcemacros RESOURCE_STATE(flag, NOBUG_RESOURCE_EXCLUSIVE, handle);
1207 //resourcemacros ----
1209 #define NOBUG_RESOURCE_WAIT(flag, resource, user, handle) \
1210 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_WAITING, handle)
1212 #define NOBUG_RESOURCE_WAIT_CTX(flag, resource, user, handle, context) \
1213 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_WAITING, handle, context)
1216 //resourcemacros PARA RESOURCE_TRY; RESOURCE_TRY; wait for a resource to become available
1217 //resourcemacros RESOURCE_TRY(flag, resource, user, handle)
1218 //resourcemacros NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context)
1220 //resourcemacros This is just an alias for RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle).
1221 //resourcemacros Trying on a resource is similar to waiting but will not trigger a deadlock check. This can be used
1222 //resourcemacros when a deadlock is expected at runtime and one handles this otherwise (by a timed wait or something like that).
1224 #define NOBUG_RESOURCE_TRY(flag, resource, user, handle) \
1225 NOBUG_RESOURCE_ENTER(flag, resource, user, NOBUG_RESOURCE_TRYING, handle)
1227 #define NOBUG_RESOURCE_TRY_CTX(flag, resource, user, handle, context) \
1228 NOBUG_RESOURCE_ENTER_CTX(flag, resource, user, NOBUG_RESOURCE_TRYING, handle, context)
1232 //resourcemacros PARA RESOURCE_STATE; RESOURCE_STATE; change the state of a resource
1233 //resourcemacros RESOURCE_STATE(flag, entered, state)
1234 //resourcemacros NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context)
1235 //resourcemacros NOBUG_RESOURCE_STATE_RAW(flagptr, state, entered)
1236 //resourcemacros NOBUG_RESOURCE_STATE_RAW_CTX(flagptr, nstate, entered, context)
1238 //resourcemacros Changes resource's state.
1240 //resourcemacros `flag`::
1241 //resourcemacros is nobug flag which turns logging on for this macro
1242 //resourcemacros `state`::
1243 //resourcemacros the new state Note that only certain state transitions are
1244 //resourcemacros allowed, see discussion/diagram above
1245 //resourcemacros `entered`::
1246 //resourcemacros the handle set by `RESOURCE_ENTER`
1249 #define NOBUG_RESOURCE_STATE(flag, state, entered) \
1250 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, NOBUG_CONTEXT)
1252 #define NOBUG_RESOURCE_STATE_CTX(flag, state, entered, context) \
1253 NOBUG_RESOURCE_STATE_RAW_CTX(&NOBUG_FLAG(flag), state, entered, context)
1255 #define NOBUG_RESOURCE_STATE_RAW(flag, state, entered) \
1256 NOBUG_RESOURCE_STATE_RAW_CTX(flag, state, entered, NOBUG_CONTEXT)
1258 #define NOBUG_RESOURCE_STATE_RAW_CTX(flag, nstate, entered, context) \
1261 NOBUG_RESOURCE_LOCK; \
1262 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1263 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1264 "RESOURCE_STATE", context, \
1265 "%s: %s@%p: %s: %s->%s", \
1266 (entered)?(entered)->current->resource->type:"", \
1267 (entered)?(entered)->current->resource->hdr.name:"", \
1268 (entered)?(entered)->current->resource->object_id:"", \
1269 (entered)?(entered)->hdr.name:"", \
1270 nobug_resource_states[(entered)?(entered)->state \
1271 :NOBUG_RESOURCE_INVALID], \
1272 nobug_resource_states[nstate]); \
1274 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_state ((entered), nstate), \
1275 "RESOURCE_ASSERT_STATE", context, \
1276 "%s: %s@%p: %s: %s->%s: %s", \
1277 (entered)?(entered)->current->resource->type:"", \
1278 (entered)?(entered)->current->resource->hdr.name:"", \
1279 (entered)?(entered)->current->resource->object_id:"", \
1280 (entered)?(entered)->hdr.name:"", \
1281 nobug_resource_states[(entered)?(entered)->state \
1282 :NOBUG_RESOURCE_INVALID], \
1283 nobug_resource_states[nstate], \
1284 nobug_resource_error); \
1285 NOBUG_RESOURCE_UNLOCK; \
1290 //resourcemacros PARA RESOURCE_LEAVE; RESOURCE_LEAVE; relinquish a claimed resource
1291 //resourcemacros RESOURCE_LEAVE(flag, handle){}
1292 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW(flagptr, handle){}
1293 //resourcemacros NOBUG_RESOURCE_LEAVE_RAW_CTX(flagptr, handle, context){}
1295 //resourcemacros Disconnect from a resource identified with its handle.
1297 //resourcemacros `flag`::
1298 //resourcemacros nobug flag which turns logging on for this macro
1299 //resourcemacros `handle`::
1300 //resourcemacros the handle you got while entering the resource
1302 //resourcemacros 'RESOURCE_LEAVE()' acts like the head of a C loop statement, it ties to the following
1303 //resourcemacros (block-) statement. Leaving and the user defined following statement are atomic.
1304 //resourcemacros This statement must not be left by break, return or any other kind of jump. NoBug does
1305 //resourcemacros not assert this (for for Performance reasons).
1307 //resourcemacros .How to use it
1308 //resourcemacros [source,c]
1309 //resourcemacros ----
1310 //resourcemacros NOBUG_RESOURCE_LEAVE(flag, handle)
1312 //resourcemacros unlock_my_resource();
1314 //resourcemacros ----
1317 #define NOBUG_RESOURCE_LEAVE(flag, handle) \
1318 NOBUG_RESOURCE_LEAVE_RAW_CTX(&NOBUG_FLAG(flag), handle, NOBUG_CONTEXT)
1320 #define NOBUG_RESOURCE_LEAVE_RAW(flag, handle) \
1321 NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, NOBUG_CONTEXT)
1323 #define NOBUG_RESOURCE_LEAVE_RAW_CTX(flag, handle, context) \
1326 int nobug_locked_ = (NOBUG_RESOURCE_LOCK, 1); \
1329 NOBUG_IF(NOBUG_RESOURCE_LOGGING, \
1330 NOBUG_LOG_(flag, NOBUG_RESOURCE_LOG_LEVEL, \
1331 "RESOURCE_LEAVE", context, \
1332 "%s: %s@%p: %s: %s", \
1333 (handle)?(handle)->current->resource->type:"", \
1334 (handle)?(handle)->current->resource->hdr.name:"", \
1335 (handle)?(handle)->current->resource->object_id:"", \
1336 (handle)?(handle)->hdr.name:"", \
1337 nobug_resource_states[(handle)?(handle)->state \
1338 :NOBUG_RESOURCE_INVALID]); \
1340 NOBUG_RESOURCE_ASSERT_CTX(nobug_resource_leave (handle), \
1341 "RESOURCE_ASSERT_LEAVE", context, \
1342 "%s: %s@%p: %s: %s: %s", \
1343 (handle)?(handle)->current->resource->type:"", \
1344 (handle)?(handle)->current->resource->hdr.name:"", \
1345 (handle)?(handle)->current->resource->object_id:"", \
1346 (handle)?(handle)->hdr.name:"", \
1347 nobug_resource_states[(handle)?(handle)->state \
1348 :NOBUG_RESOURCE_INVALID], \
1349 nobug_resource_error); \
1351 NOBUG_RESOURCE_UNLOCK; \
1352 nobug_locked_ = 0; \
1357 //resourcemacros PARA RESOURCE_ASSERT_STATE; RESOURCE_ASSERT_STATE; assert the state of a resource
1358 //resourcemacros RESOURCE_ASSERT_STATE(resource, state)
1359 //resourcemacros RESOURCE_ASSERT_STATE_IF(when, resource, state)
1360 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context)
1361 //resourcemacros NOBUG_RESOURCE_ASSERT_STATE_IF_CTX(when, resource, state, context)
1363 //resourcemacros Assert that we have a resource in a given state. For multithreaded programms the topmost
1364 //resourcemacros state of the calling thread is checked, for non threadeded programs the most recent state on
1365 //resourcemacros resource is used.
1367 //resourcemacros `when`::
1368 //resourcemacros Condition which must be true for testing the assertion
1369 //resourcemacros `resource`::
1370 //resourcemacros Resource handle
1371 //resourcemacros `state`::
1372 //resourcemacros The expected state
1375 #define NOBUG_RESOURCE_ASSERT_STATE(resource, state) \
1376 NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, NOBUG_CONTEXT)
1378 #define NOBUG_RESOURCE_ASSERT_STATE_CTX(resource, state, context) \
1380 enum nobug_resource_state mystate = nobug_resource_mystate (resource); \
1381 NOBUG_RESOURCE_ASSERT_CTX(mystate == state, \
1382 "RESOURCE_ASSERT_STATE", context, \
1383 "resource %p has state %s but %s was expected", \
1384 resource, nobug_resource_states[mystate], nobug_resource_states[state]); \
1388 #define NOBUG_RESOURCE_ASSERT_STATE_IF(when, resource, state) \
1389 NOBUG_IF_ALPHA (NOBUG_WHEN(when, NOBUG_RESOURCE_ASSERT_STATE (resource, state))
1392 /* assertion which dumps all resources */
1393 #define NOBUG_RESOURCE_ASSERT_CTX(expr, what, context, ...) \
1395 NOBUG_WHEN (!(expr), \
1396 NOBUG_LOG_( &nobug_flag_NOBUG_ON, LOG_EMERG, \
1399 nobug_resource_dump_all ((struct nobug_resource_dump_context) \
1401 &nobug_flag_NOBUG_ON, \
1405 NOBUG_BACKTRACE_CTX(context); \
1410 //resourcemacros PARA RESOURCE_DUMP; RESOURCE_DUMP; dump the state of a single resource
1411 //resourcemacros NOBUG_RESOURCE_DUMP(flag, handle)
1412 //resourcemacros NOBUG_RESOURCE_DUMP_IF(when, flag, handle)
1414 //resourcemacros Dump the state of a single resource.
1416 //resourcemacros `when`::
1417 //resourcemacros Condition which must be true to dump the resource
1418 //resourcemacros `flag`::
1419 //resourcemacros Nobug flag for the log channel
1420 //resourcemacros `handle`::
1421 //resourcemacros handle of the resource to be dumped
1424 #define NOBUG_RESOURCE_DUMP(flag, handle) \
1427 NOBUG_RESOURCE_LOCK; \
1428 nobug_resource_dump (handle, (struct nobug_resource_dump_context) \
1429 {&NOBUG_FLAG(flag), \
1430 NOBUG_RESOURCE_LOG_LEVEL, \
1432 NOBUG_RESOURCE_UNLOCK; \
1435 #define NOBUG_RESOURCE_DUMP_IF(when, flag, handle) \
1437 NOBUG_WHEN(when, NOBUG_RESOURCE_LOCK; \
1438 nobug_resource_dump (handle, (struct nobug_resource_dump_context) \
1439 {&NOBUG_FLAG(flag), \
1440 NOBUG_RESOURCE_LOG_LEVEL, \
1442 NOBUG_RESOURCE_UNLOCK))
1446 //resourcemacros PARA RESOURCE_DUMPALL; RESOURCE_DUMPALL; dump the state of all resources
1447 //resourcemacros NOBUG_RESOURCE_DUMPALL(flag)
1448 //resourcemacros NOBUG_RESOURCE_DUMPALL_IF(when, flag)
1450 //resourcemacros Dump the state of all resources.
1452 //resourcemacros `when`::
1453 //resourcemacros Condition which must be true to dump the resources
1454 //resourcemacros `flag`::
1455 //resourcemacros Nobug flag for the log channel
1458 #define NOBUG_RESOURCE_DUMPALL(flag) \
1461 NOBUG_RESOURCE_LOCK; \
1462 nobug_resource_dump_all ((struct nobug_resource_dump_context) \
1463 {&NOBUG_FLAG(flag), \
1464 NOBUG_RESOURCE_LOG_LEVEL, \
1466 NOBUG_RESOURCE_UNLOCK; \
1470 #define NOBUG_RESOURCE_DUMPALL_IF(when, flag) \
1473 NOBUG_RESOURCE_LOCK; \
1474 nobug_resource_dump_all ((struct nobug_resource_dump_context) \
1475 {&NOBUG_FLAG(flag), \
1476 NOBUG_RESOURCE_LOG_LEVEL, \
1478 NOBUG_RESOURCE_UNLOCK))
1481 //resourcemacros PARA RESOURCE_LIST; RESOURCE_LIST; enumerate all registered resources
1482 //resourcemacros NOBUG_RESOURCE_LIST(flag)
1483 //resourcemacros NOBUG_RESOURCE_LIST_IF(when, flag)
1485 //resourcemacros List all registered resources.
1487 //resourcemacros `when`::
1488 //resourcemacros Condition which must be true to list the resources
1489 //resourcemacros `flag`::
1490 //resourcemacros Nobug flag for the log channel
1493 #define NOBUG_RESOURCE_LIST(flag) \
1496 NOBUG_RESOURCE_LOCK; \
1497 nobug_resource_list ((struct nobug_resource_dump_context) \
1498 {&NOBUG_FLAG(flag), \
1499 NOBUG_RESOURCE_LOG_LEVEL, \
1501 NOBUG_RESOURCE_UNLOCK; \
1505 #define NOBUG_RESOURCE_LIST_IF(when, flag) \
1508 NOBUG_RESOURCE_LOCK; \
1509 nobug_resource_list ((struct nobug_resource_dump_context) \
1510 {&NOBUG_FLAG(flag), \
1511 NOBUG_RESOURCE_LOG_LEVEL, \
1513 NOBUG_RESOURCE_UNLOCK))
1519 #if NOBUG_USE_PTHREAD
1520 #define NOBUG_THREAD_ID_SET(name) nobug_thread_id_set(name)
1521 #define NOBUG_THREAD_ID_GET nobug_thread_id_get()
1524 #define NOBUG_THREAD_ID_SET(name)
1525 #define NOBUG_THREAD_ID_GET ""
1528 #define NOBUG_THREAD_DATA (*nobug_thread_data())
1535 #define NOBUG_DBG_NONE 0
1536 #define NOBUG_DBG_GDB 1
1537 #define NOBUG_DBG_VALGRIND 2
1539 #define NOBUG_ACTIVE_DBG \
1540 NOBUG_IF(NOBUG_USE_VALGRIND, (RUNNING_ON_VALGRIND?2:0)) \
1541 NOBUG_IFNOT(NOBUG_USE_VALGRIND, 0)
1544 //toolmacros HEAD- Tool Macros;;
1546 //toolmacros PARA NOBUG_FLAG_RAW; NOBUG_FLAG_RAW; pass direct flag pointer
1547 //toolmacros NOBUG_FLAG_RAW(ptr)
1549 //toolmacros Using this macro one can pass a direct pointer to a flag where a name would
1550 //toolmacros be expected. This is sometimes convinient when flag pointers are passed around
1551 //toolmacros in management strutures and one wants to tie logging to dynamic targets.
1553 //toolmacros [source,c]
1555 //toolmacros NOBUG_DEFINE_FLAG(myflag);
1557 //toolmacros struct nobug_flag* ptr = &NOBUG_FLAG(myflag);
1558 //toolmacros TRACE(NOBUG_FLAG_RAW(ptr), "Passed flag by pointer")
1562 #define nobug_flag_NOBUG_FLAG_RAW(name) *name
1565 //toolmacros PARA Backtraces; BACKTRACE; generate a backtrace
1566 //toolmacros BACKTRACE
1567 //toolmacros NOBUG_BACKTRACE_CTX(context)
1569 //toolmacros The backtrace macro logs a stacktrace using the NoBug facilities.
1570 //toolmacros This is automatically called when NoBug finds an error and is due
1571 //toolmacros to abort. But one might call it manually too.
1574 #define NOBUG_BACKTRACE NOBUG_BACKTRACE_CTX(NOBUG_CONTEXT)
1576 #define NOBUG_BACKTRACE_CTX(context) \
1578 switch (NOBUG_ACTIVE_DBG) { \
1579 case NOBUG_DBG_VALGRIND: \
1580 NOBUG_BACKTRACE_VALGRIND(context); \
1583 NOBUG_BACKTRACE_GLIBC(context); \
1585 NOBUG_IF_NOT_ALPHA (NOBUG_BACKTRACE_GLIBC(context))
1587 #define NOBUG_BACKTRACE_GDB(context) UNIMPLEMENTED
1589 #define NOBUG_BACKTRACE_VALGRIND(context) \
1590 NOBUG_IF(NOBUG_USE_VALGRIND, \
1591 NOBUG_LOGGING_LOCK; \
1592 struct nobug_context ctx = context; \
1593 VALGRIND_PRINTF_BACKTRACE("----------: BACKTRACE: %s@%d %s", \
1594 nobug_basename(ctx.file), \
1597 NOBUG_LOGGING_UNLOCK)
1599 #ifndef NOBUG_BACKTRACE_DEPTH
1600 #define NOBUG_BACKTRACE_DEPTH 256
1603 #define NOBUG_BACKTRACE_GLIBC(context) \
1604 NOBUG_IF_NOT_RELEASE( \
1605 NOBUG_IF(NOBUG_USE_EXECINFO, do { \
1606 nobug_backtrace_glibc (context); \
1611 #define NOBUG_TAB " "
1614 //toolmacros PARA Aborting; ABORT; abort the program
1615 //toolmacros NOBUG_ABORT_
1617 //toolmacros This is the default implementation for aborting the program, it first syncs all ringbuffers to disk, then
1618 //toolmacros calls the abort callback if defined and then `abort()`.
1620 //toolmacros NOBUG_ABORT
1622 //toolmacros If not overridden, evaluates to `NOBUG_ABORT_`. One can override this before including
1623 //toolmacros `nobug.h` to customize abortion behaviour. This will be local to the translation unit then.
1626 #define NOBUG_ABORT NOBUG_ABORT_
1629 #define NOBUG_ABORT_ \
1631 nobug_ringbuffer_allsync (); \
1632 if (nobug_abort_callback) \
1633 nobug_abort_callback (nobug_callback_data); \
1639 init and other function wrapers
1641 #define NOBUG_INIT nobug_init(NOBUG_CONTEXT)
1644 short macros without NOBUG_
1646 #ifndef NOBUG_DISABLE_SHORTNAMES
1648 #define REQUIRE NOBUG_REQUIRE
1651 #define REQUIRE_IF NOBUG_REQUIRE_IF
1654 #define ENSURE NOBUG_ENSURE
1657 #define ENSURE_IF NOBUG_ENSURE_IF
1660 #define ASSERT NOBUG_ASSERT
1663 #define ASSERT_IF NOBUG_ASSERT_IF
1666 #define CHECK NOBUG_CHECK
1669 #define CHECK NOBUG_CHECK
1672 #define INVARIANT NOBUG_INVARIANT
1674 #ifndef INVARIANT_IF
1675 #define INVARIANT_IF NOBUG_INVARIANT_IF
1677 #ifndef INVARIANT_ASSERT
1678 #define INVARIANT_ASSERT NOBUG_INVARIANT_ASSERT
1681 #define DUMP NOBUG_DUMP
1684 #define DUMP_IF NOBUG_DUMP_IF
1687 #define DUMP_LOG NOBUG_DUMP_LOG
1690 #define DUMP_LOG_IF NOBUG_DUMP_LOG_IF
1693 #define LOG NOBUG_LOG
1696 #define LOG_IF NOBUG_LOG_IF
1699 #define ECHO NOBUG_ECHO
1702 #define ALERT NOBUG_ALERT
1705 #define ALERT_IF NOBUG_ALERT_IF
1708 #define CRITICAL NOBUG_CRITICAL
1711 #define CRITICAL_IF NOBUG_CRITICAL_IF
1714 #define ERROR NOBUG_ERROR
1717 #define ERROR_IF NOBUG_ERROR_IF
1720 #define WARN NOBUG_WARN
1723 #define WARN_IF NOBUG_WARN_IF
1726 #define INFO NOBUG_INFO
1729 #define INFO_IF NOBUG_INFO_IF
1732 #define NOTICE NOBUG_NOTICE
1735 #define NOTICE_IF NOBUG_NOTICE_IF
1738 #define TRACE NOBUG_TRACE
1741 #define TRACE_IF NOBUG_TRACE_IF
1744 #define BACKTRACE NOBUG_BACKTRACE
1747 #define DEPRECATED NOBUG_DEPRECATED
1749 #ifndef UNIMPLEMENTED
1750 #define UNIMPLEMENTED NOBUG_UNIMPLEMENTED
1753 #define FIXME NOBUG_FIXME
1756 #define TODO NOBUG_TODO
1759 #define PLANNED NOBUG_PLANNED
1762 #define NOTREACHED NOBUG_NOTREACHED
1764 #ifndef ELSE_NOTREACHED
1765 #define ELSE_NOTREACHED NOBUG_ELSE_NOTREACHED
1767 #ifndef INJECT_GOODBAD
1768 #define INJECT_GOODBAD NOBUG_INJECT_GOODBAD
1770 #ifndef INJECT_FAULT
1771 #define INJECT_FAULT NOBUG_INJECT_FAULT
1774 #define CLEANUP NOBUG_CLEANUP
1777 #define CHECKED NOBUG_CHECKED
1780 #define UNCHECKED NOBUG_UNCHECKED
1782 #ifndef RESOURCE_ANNOUNCE
1783 #define RESOURCE_ANNOUNCE NOBUG_RESOURCE_ANNOUNCE
1785 #ifndef RESOURCE_FORGET
1786 #define RESOURCE_FORGET NOBUG_RESOURCE_FORGET
1788 #ifndef RESOURCE_ENTER
1789 #define RESOURCE_ENTER NOBUG_RESOURCE_ENTER
1791 #ifndef RESOURCE_WAIT
1792 #define RESOURCE_WAIT NOBUG_RESOURCE_WAIT
1794 #ifndef RESOURCE_TRY
1795 #define RESOURCE_TRY NOBUG_RESOURCE_TRY
1797 #ifndef RESOURCE_STATE
1798 #define RESOURCE_STATE NOBUG_RESOURCE_STATE
1800 #ifndef RESOURCE_LEAVE
1801 #define RESOURCE_LEAVE NOBUG_RESOURCE_LEAVE
1803 #ifndef RESOURCE_LEAVE_LOOKUP
1804 #define RESOURCE_LEAVE_LOOKUP NOBUG_RESOURCE_LEAVE_LOOKUP
1806 #ifndef RESOURCE_HANDLE
1807 #define RESOURCE_HANDLE NOBUG_RESOURCE_HANDLE
1809 #ifndef RESOURCE_HANDLE_INIT
1810 #define RESOURCE_HANDLE_INIT NOBUG_RESOURCE_HANDLE_INIT
1812 #ifndef RESOURCE_USER
1813 #define RESOURCE_USER NOBUG_RESOURCE_USER
1815 #ifndef RESOURCE_ASSERT_STATE
1816 #define RESOURCE_ASSERT_STATE NOBUG_RESOURCE_ASSERT_STATE
1818 #ifndef RESOURCE_ASSERT_STATE_IF
1819 #define RESOURCE_ASSERT_STATE_IF NOBUG_RESOURCE_ASSERT_STATE_IF
1821 #ifndef RESOURCE_USER_INIT
1822 #define RESOURCE_USER_INIT NOBUG_RESOURCE_USER_INIT
1824 #ifndef RESOURCE_DUMP
1825 #define RESOURCE_DUMP NOBUG_RESOURCE_DUMP
1827 #ifndef RESOURCE_DUMP_IF
1828 #define RESOURCE_DUMP_IF NOBUG_RESOURCE_DUMP_IF
1830 #ifndef RESOURCE_DUMPALL
1831 #define RESOURCE_DUMPALL NOBUG_RESOURCE_DUMPALL
1833 #ifndef RESOURCE_DUMPALL_IF
1834 #define RESOURCE_DUMPALL_IF NOBUG_RESOURCE_DUMPALL_IF
1836 #ifndef RESOURCE_LIST
1837 #define RESOURCE_LIST NOBUG_RESOURCE_LIST
1839 #ifndef RESOURCE_LIST_IF
1840 #define RESOURCE_LIST_IF NOBUG_RESOURCE_LIST_IF
1842 #endif /* NOBUG_DISABLE_SHORTNAMES */
1849 #define NOBUG_CLEANUP(fn) NOBUG_IF_ALPHA(__attribute__((cleanup(fn))))
1850 #define NOBUG_ATTR_PRINTF(fmt, ell) __attribute__ ((format (printf, fmt, ell)))
1852 #define NOBUG_CLEANUP(fn)
1853 #define NOBUG_ATTR_PRINTF(fmt, ell)
1857 //toolmacros PARA NOBUG_ALPHA_COMMA; NOBUG_ALPHA_COMMA; append something after a comma in *ALPHA* builds
1858 //toolmacros NOBUG_ALPHA_COMMA(something)
1859 //toolmacros NOBUG_ALPHA_COMMA_NULL
1861 //toolmacros Sometimes it is useful to have initializer code only in *ALPHA* builds, for example when you
1862 //toolmacros conditionally include resource handles only in *ALPHA* versions. An initializer can then
1863 //toolmacros use this macros to append a comman and something else only in *ALPHA* builds as in:
1864 //toolmacros struct foo = {"foo", "bar" NOBUG_ALPHA_COMMA_NULL };
1867 #define NOBUG_COMMA ,
1868 #define NOBUG_ALPHA_COMMA(something) NOBUG_IF_ALPHA(NOBUG_COMMA something)
1869 #define NOBUG_ALPHA_COMMA_NULL NOBUG_ALPHA_COMMA(NULL)
1871 #define NOBUG_ONCE(code) \
1873 static volatile int NOBUG_CAT(nobug_once_,__LINE__) = 1; \
1874 if (NOBUG_EXPECT_FALSE(NOBUG_CAT(nobug_once_,__LINE__))) \
1876 NOBUG_CAT(nobug_once_,__LINE__) = 0; \
1882 #define NOBUG_EXPECT_FALSE(x) __builtin_expect(!!(x),0)
1884 #define NOBUG_EXPECT_FALSE(x) x
1887 #define NOBUG_WHEN(when, ...) \
1888 do{ if (NOBUG_EXPECT_FALSE(when)){ __VA_ARGS__;}} while(0)
1891 //toolmacros PARA NOBUG_IF_*; NOBUG_IF; include code conditionally on build level
1892 //toolmacros NOBUG_IF_ALPHA(...)
1893 //toolmacros NOBUG_IF_NOT_ALPHA(...)
1894 //toolmacros NOBUG_IF_BETA(...)
1895 //toolmacros NOBUG_IF_NOT_BETA(...)
1896 //toolmacros NOBUG_IF_RELEASE(...)
1897 //toolmacros NOBUG_IF_NOT_RELEASE(...)
1899 //toolmacros This macros allow one to conditionally include the code in '(...)' only if the
1900 //toolmacros criteria on the build level is met. If not, nothing gets substituted. Mostly used
1901 //toolmacros internally, but can also be used for custom things.
1904 #define NOBUG_IF_ALPHA(...) \
1905 NOBUG_IF(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1907 #define NOBUG_IF_NOT_ALPHA(...) \
1908 NOBUG_IFNOT(NOBUG_MODE_ALPHA, __VA_ARGS__) \
1910 #define NOBUG_IF_BETA(...) \
1911 NOBUG_IF(NOBUG_MODE_BETA, __VA_ARGS__) \
1913 #define NOBUG_IF_NOT_BETA(...) \
1914 NOBUG_IFNOT(NOBUG_MODE_BETA, __VA_ARGS__) \
1916 #define NOBUG_IF_RELEASE(...) \
1917 NOBUG_IF(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1919 #define NOBUG_IF_NOT_RELEASE(...) \
1920 NOBUG_IFNOT(NOBUG_MODE_RELEASE, __VA_ARGS__) \
1923 preprocessor hacks/metaprogramming
1926 #define NOBUG_IF(bool, ...) NOBUG_CAT(NOBUG_IF_,bool)(__VA_ARGS__)
1927 #define NOBUG_IF_1(...) __VA_ARGS__
1928 #define NOBUG_IF_0(...)
1930 #define NOBUG_IFNOT(bool, ...) NOBUG_CAT(NOBUG_IF_, NOBUG_NOT(bool))(__VA_ARGS__)
1932 #define NOBUG_NOT(bool) NOBUG_CAT(NOBUG_NOT_, bool)
1933 #define NOBUG_NOT_1 0
1934 #define NOBUG_NOT_0 1
1936 #define NOBUG_AND(a,b) NOBUG_CAT3(NOBUG_AND_, a, b)
1937 #define NOBUG_AND_00 0
1938 #define NOBUG_AND_01 0
1939 #define NOBUG_AND_10 0
1940 #define NOBUG_AND_11 1
1942 #define NOBUG_OR(a,b) NOBUG_CAT3(NOBUG_OR_, a, b)
1943 #define NOBUG_OR_00 0
1944 #define NOBUG_OR_01 1
1945 #define NOBUG_OR_10 1
1946 #define NOBUG_OR_11 1
1948 #define NOBUG_XOR(a,b) NOBUG_CAT( NOBUG_XOR_, NOBUG_CAT(a,b))
1949 #define NOBUG_XOR_00 0
1950 #define NOBUG_XOR_01 1
1951 #define NOBUG_XOR_10 1
1952 #define NOBUG_XOR_11 0
1954 #define NOBUG_CAT(a,b) NOBUG_CAT_(a,b)
1955 #define NOBUG_CAT_(a,b) a##b
1957 #define NOBUG_CAT3(a,b,c) NOBUG_CAT3_(a,b,c)
1958 #define NOBUG_CAT3_(a,b,c) a##b##c
1960 #define NOBUG_STRINGIZE(s) NOBUG_STRINGIZE_(s)
1961 #define NOBUG_STRINGIZE_(s) #s
1965 LIBNOBUG DECLARATIONS
1970 } /* fix emacs indent */
1973 #ifndef LLIST_DEFINED
1974 #define LLIST_DEFINED
1977 struct llist_struct
*next
;
1978 struct llist_struct
*prev
;
1986 struct nobug_context
1994 nobug_basename (const char* const file
);
1999 enum nobug_log_targets
2001 NOBUG_TARGET_RINGBUFFER
,
2002 NOBUG_TARGET_CONSOLE
,
2004 NOBUG_TARGET_SYSLOG
,
2005 NOBUG_TARGET_APPLICATION
2011 struct nobug_flag
* parent
;
2012 volatile int initialized
;
2014 struct nobug_ringbuffer
* ringbuffer_target
;
2015 FILE* console_target
;
2020 nobug_env_parse_flag (const char* env
, struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
);
2023 nobug_env_init_flag (struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
);
2029 struct nobug_ringbuffer
2031 struct llist_struct node
; /* all ringbufers are chained together, needed for sync */
2039 enum nobug_ringbuffer_flags
2041 NOBUG_RINGBUFFER_DEFAULT
, /* Default is to overwrite file and delete it on nobug_ringbuffer_destroy */
2042 NOBUG_RINGBUFFER_APPEND
= 1, /* use existing backing file, append if possible */
2043 NOBUG_RINGBUFFER_TEMP
= 2, /* unlink file instantly */
2044 NOBUG_RINGBUFFER_KEEP
= 4 /* dont unlink the file at destroy */
2047 Note: some flags conflict (TEMP with KEEP) nobug_ringbuffer will not error on these but continue gracefully
2048 with sane (but undefined) semantics.
2051 struct nobug_ringbuffer
*
2052 nobug_ringbuffer_init (struct nobug_ringbuffer
* self
, size_t size
,
2053 size_t guard
, const char * name
, int flags
);
2055 struct nobug_ringbuffer
*
2056 nobug_ringbuffer_new (size_t size
, size_t guard
, const char * name
, int flags
);
2058 struct nobug_ringbuffer
*
2059 nobug_ringbuffer_destroy (struct nobug_ringbuffer
* self
);
2062 nobug_ringbuffer_delete (struct nobug_ringbuffer
* self
);
2065 nobug_ringbuffer_sync (struct nobug_ringbuffer
* self
);
2068 nobug_ringbuffer_allsync (void);
2071 nobug_ringbuffer_vprintf (struct nobug_ringbuffer
* self
, const char* fmt
, va_list ap
);
2074 nobug_ringbuffer_printf (struct nobug_ringbuffer
* self
, const char* fmt
, ...);
2077 nobug_ringbuffer_append (struct nobug_ringbuffer
* self
);
2080 nobug_ringbuffer_extend (struct nobug_ringbuffer
* self
, size_t newsize
, const char fill
);
2083 nobug_ringbuffer_prev (struct nobug_ringbuffer
* self
, char* pos
);
2086 nobug_ringbuffer_next (struct nobug_ringbuffer
* self
, char* pos
);
2089 nobug_ringbuffer_save (struct nobug_ringbuffer
* self
, FILE* out
);
2092 nobug_ringbuffer_load (struct nobug_ringbuffer
* self
, FILE* in
);
2095 nobug_ringbuffer_pos (struct nobug_ringbuffer
* self
);
2098 nobug_ringbuffer_pop (struct nobug_ringbuffer
* self
);
2102 multithreading extras
2104 #if NOBUG_USE_PTHREAD
2106 struct nobug_tls_data
2108 const char* thread_id
;
2109 unsigned thread_num
; /* thread counter at initialization, gives a unique thread number */
2110 unsigned thread_gen
; /* incremented at each name reset, (currently unused) */
2112 struct llist_struct res_stack
; /* resources of this thread */
2115 extern pthread_key_t nobug_tls_key
;
2117 struct nobug_tls_data
*
2118 nobug_thread_set (const char* name
);
2120 struct nobug_tls_data
*
2121 nobug_thread_get (void);
2124 nobug_thread_id_set (const char* name
);
2127 nobug_thread_id_get (void);
2129 extern pthread_mutex_t nobug_logging_mutex
;
2130 extern pthread_mutex_t nobug_resource_mutex
;
2134 nobug_thread_data (void);
2140 #if NOBUG_USE_PTHREAD
2141 #define NOBUG_RESOURCE_LOCK pthread_mutex_lock (&nobug_resource_mutex)
2142 #define NOBUG_RESOURCE_UNLOCK pthread_mutex_unlock (&nobug_resource_mutex)
2143 #define NOBUG_LOGGING_LOCK pthread_mutex_lock (&nobug_logging_mutex)
2144 #define NOBUG_LOGGING_UNLOCK pthread_mutex_unlock (&nobug_logging_mutex)
2146 #define NOBUG_RESOURCE_LOCK
2147 #define NOBUG_RESOURCE_UNLOCK
2148 #define NOBUG_LOGGING_LOCK
2149 #define NOBUG_LOGGING_UNLOCK
2152 enum nobug_resource_state
2154 NOBUG_RESOURCE_INVALID
,
2155 NOBUG_RESOURCE_WAITING
,
2156 NOBUG_RESOURCE_TRYING
,
2157 NOBUG_RESOURCE_EXCLUSIVE
,
2158 NOBUG_RESOURCE_RECURSIVE
,
2159 NOBUG_RESOURCE_SHARED
2163 struct nobug_resource_header
2165 struct llist_struct node
; /* link node for resource registry or users */
2166 const char* name
; /* name */
2167 struct nobug_context extra
; /* context information */
2170 struct nobug_resource_node
;
2171 struct nobug_resource_user
;
2173 struct nobug_resource_record
2175 struct nobug_resource_header hdr
;
2177 struct llist_struct users
; /* list of users of this resource */
2178 const void* object_id
; /* unique identifer, usually a this pointer or similar */
2179 const char* type
; /* type */
2181 #if NOBUG_USE_PTHREAD
2182 struct llist_struct nodes
;
2187 struct nobug_resource_node
2189 struct llist_struct node
; /* all nodes for one resource */
2191 struct nobug_resource_record
* resource
; /* backpointer */
2192 struct nobug_resource_node
* parent
; /* upwards the tree */
2194 struct llist_struct childs
; /* down the tree, all nodes pointing to here (TODO make this a slist) */
2195 struct llist_struct cldnode
; /* node to accumulate all childrens of a parent (TODO slist) */
2199 struct nobug_resource_user
2201 struct nobug_resource_header hdr
;
2203 struct nobug_resource_node
* current
; /* this resource */
2204 enum nobug_resource_state state
; /* state */
2206 #if NOBUG_USE_PTHREAD
2207 struct nobug_tls_data
* thread
; /* pointer to this theads id */
2208 struct llist_struct res_stack
; /* resources of this thread */
2213 extern const char* nobug_resource_error
;
2215 extern const char* nobug_resource_states
[];
2219 nobug_resource_init (void);
2222 nobug_resource_destroy (void);
2225 struct nobug_resource_record
*
2226 nobug_resource_announce (const char* type
, const char* name
, const void* object_id
, const struct nobug_context extra
);
2229 nobug_resource_forget (struct nobug_resource_record
* node
);
2232 struct nobug_resource_user
*
2233 nobug_resource_enter (struct nobug_resource_record
* resource
,
2235 enum nobug_resource_state state
,
2236 const struct nobug_context extra
);
2239 nobug_resource_leave (struct nobug_resource_user
* handle
);
2243 nobug_resource_record_available (void);
2247 nobug_resource_user_available (void);
2250 #if NOBUG_USE_PTHREAD
2252 nobug_resource_node_available (void);
2256 struct nobug_resource_dump_context
2258 struct nobug_flag
* flag
;
2260 struct nobug_context ctx
;
2263 enum nobug_resource_state
2264 nobug_resource_mystate (struct nobug_resource_record
* res
);
2267 nobug_resource_dump (struct nobug_resource_record
* resource
, const struct nobug_resource_dump_context context
);
2270 nobug_resource_dump_all (const struct nobug_resource_dump_context context
);
2273 nobug_resource_state (struct nobug_resource_user
* resource
,
2274 enum nobug_resource_state state
);
2278 nobug_resource_list (const struct nobug_resource_dump_context context
);
2282 global config, data and defaults
2284 void nobug_init (const struct nobug_context context
);
2287 the destroy function is optional, since nobug should stay alive for the whole application lifetime
2288 (and destroying is global!) it is only provided for the nobug testsuite itself
2290 void nobug_destroy (const struct nobug_context context
);
2293 nobug_backtrace_glibc (const struct nobug_context context
);
2297 nobug_log_begin (char* header
, struct nobug_flag
* flag
, const char* what
, const struct nobug_context ctx
);
2301 nobug_log_end (struct nobug_flag
* flag
, int lvl
);
2304 /* must be called inbetween log_begin and log_end */
2306 nobug_log_line (char** start
, char* header
, struct nobug_flag
* flag
, int lvl
, const char* fmt
, ...);
2310 nobug_log (struct nobug_flag
* flag
, int lvl
, const char* what
,
2311 const struct nobug_context ctx
,
2312 const char* fmt
, ...) NOBUG_ATTR_PRINTF(5, 6);
2315 extern struct nobug_ringbuffer nobug_default_ringbuffer
;
2316 extern FILE* nobug_default_file
;
2317 extern struct nobug_flag nobug_flag_NOBUG_ON
;
2318 extern struct nobug_flag nobug_flag_NOBUG_ANN
;
2319 extern struct nobug_flag nobug_flag_nobug
;
2320 extern unsigned long long nobug_counter
;
2322 //callbacks HEAD- Callbacks;;
2324 //callbacks NoBug provides callbacks, applications can use these
2325 //callbacks to present logging information in some custom way or hook some special processing in.
2326 //callbacks The callbacks are initialized to NULL and never modified by NoBug, its the solve responsibility
2327 //callbacks of the user to manage them.
2329 //callbacks CAUTION: There are certain constraints what and what not can be done in callbacks
2330 //callbacks documented below which must be followed.
2332 //callbacks PARA type of logging callbacks; logging_cb; type of a logging callback function
2333 typedef void (*nobug_logging_cb
)(const struct nobug_flag
* flag
, int priority
, const char *log
, void* data
); //callbacks VERBATIM;
2335 //callbacks used for the logging callbacks
2337 //callbacks `flag`::
2338 //callbacks Flag structure which defines the logging configuration for this event
2339 //callbacks `priority`::
2340 //callbacks Log level of the current event
2342 //callbacks Pointing to the current log line in the ringbuffer or `NULL`
2343 //callbacks `data`::
2344 //callbacks Global pointer defined by the user, passed arround (see below)
2347 //callbacks PARA type of abort callback; abort_cb; type of a abort callback function
2348 typedef void (*nobug_abort_cb
)(void* data
); //callbacks VERBATIM;
2350 //callbacks used for the abort callback
2352 //callbacks `data`::
2353 //callbacks Global data defined by the user, passed arround (see below)
2356 //callbacks PARA passing data to callbacks; callback_data; data to be passed to callbacks
2358 void* nobug_callback_data
; //callbacks VERBATIM;
2360 //callbacks This global variable is initialized to `NULL` and will never be touched by NoBug. One can use it
2361 //callbacks to pass extra data to the callback functions.
2364 //callbacks PARA callback when logging; logging_callback; hook when something get logged
2366 nobug_logging_cb nobug_logging_callback
; //callbacks VERBATIM;
2368 //callbacks This callback gets called when something gets logged.
2369 //callbacks NoBug will still hold its mutexes when calling this hook, calling NoBug logging or resource tracking
2370 //callbacks functions from here recursively will deadlock and must be avoided.
2371 //callbacks The `log` parameter points to the logging message in the ringbuffer.
2372 //callbacks Unlike other logging targets it is not automatically limited to the log level configured
2373 //callbacks in the flag but called unconditionally. The callback should implement its own limiting.
2375 //callbacks When one wants to do complex calls which may include recursion into logging and resource tracking
2376 //callbacks functions, the intended way is to pass contextual information possibly including a __copy__ of the
2377 //callbacks `log` parameter in xref:THREAD_DATA[NOBUG_THREAD_DATA] to the postlogging callback (see below).
2378 //callbacks Other internal NoBug facilties, like the ringbuffer etc, are protected by the mutexes and may be accessed
2379 //callbacks from this function.
2382 //callbacks PARA callback after logging; postlogging_callback; hook after something get logged
2384 nobug_logging_cb nobug_postlogging_callback
; //callbacks VERBATIM;
2386 //callbacks This callback gets called after something got logged. The `log` parameter is always NULL and all
2387 //callbacks NoBug mutexes are released. This means that this function may call any complex things, including
2388 //callbacks calling logging and resource tracking, but may not call internal NoBug facilities.
2389 //callbacks Contextual created in the `nobug_logging_callback` and stored in xref:THREAD_DATA[NOBUG_THREAD_DATA] can be
2390 //callbacks retrieved here and may need to be cleaned up here.
2393 //callbacks PARA callback for aborting; abort_callback; hook to handle a termination
2395 nobug_abort_cb nobug_abort_callback
; //callbacks VERBATIM;
2397 //callbacks This callback gets called when the application shall be terminated due an error.
2398 //callbacks It can be used to hook exceptions or similar things in. When it returns, `abort()`
2399 //callbacks is called.
2401 //callbacks IMPORTANT: Errors detected by NoBug are always fatal. If one handles and possible
2402 //callbacks throws an exception here, the application must shut down as soon as possible.
2403 //callbacks Most causes for aborts are optimitzed out in `RELEASE` builds.
2410 #ifndef NOBUG_LIBNOBUG_C
2413 tag this translation unit as unchecked in ALPHA and BETA builds
2415 NOBUG_IF_NOT_RELEASE(NOBUG_UNCHECKED
);
2418 /* some configuration when compiling nobug */
2419 /* Maximal length of a log line header (silently truncated if exceed) */
2420 #define NOBUG_MAX_LOG_HEADER_SIZE 128
2421 /* Maximal linebreaks in a single logging instruction which get translated to multiple lines */
2422 #define NOBUG_MAX_LOG_LINES 32
2424 #endif /* NOBUG_LIBNOBUG_C */