Document the NOBUG_IF_* macros
[nobug.git] / README.txt
blobb2c7caf63b44edeb2671c475aa29e1787cb57432
1 NoBug Documentation
2 ===================
4 [paradef-literal]
5  Everyone makes errors, but with NoBug you won't make them twice!
7 Nobug is a simple debugging library for instrumenting C and C++ programs
8 inspired by ideas originating from Design-by-Contract.
10 Overview
11 --------
13 The following features are provided by NoBug:
15   * Three different check levels: from detailed to final no-overhead
16   * Scope tags: tell whenever a function or loop is considered to be bug free
17   * Precondition, Postcondition and Invariant checks and generic assertions
18   * Debugger support (actions are only executed while running under a
19     debugger), currently only valgrind is supported
20   * Datastructures can be dumped
21   * Application activities can be logged
22   * Runtime customizable logging via an environment variable
23   * Different logging targets to stderr, syslog, debugger, ...
24   * Annotation of your sourcecode about known bugs, things to do, etc.
25   * Tracking resources (files, locks, etc.) used by your program; help in
26     detecting misuse
27   * Detecting deadlocks
29 In contrast to traditional debuggers, NoBug is a non-interactive debugger which
30 is linked to your application doing hard-coded tests in an efficient,
31 low-overhead way.
33 Building and Installing
34 -----------------------
36 Release Tarballs
37 ~~~~~~~~~~~~~~~~
39 Release tarballs are attached to this wiki at:
41   * http://pipawiki/NoBug?action=AttachFile
43 Gpg signed tarballs are being used for distribution. The first step involves
44 checking the signature:
46 $ gpg nobug-X.Y.tar.gz.gpg
48 This will produce a nobug-X.Y.tar.gz and report if the signature could be
49 validated.
51 Since they are built with gnu autotools, the usual build and install procedure
52 will work:
54 $ tar xzvf nobug-X.Y.tar.gz
55 $ cd nobug-X.Y
56 $ ./configure
57 $ make
58 $ make install
60 Development Version via git
61 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
63 The development version is available via git from 'git://git.pipapo.org/nobug'
64 or mirrored at repo.or.cz 'git://repo.or.cz/nobug.git'.
66 After you have cloned the repository, you'll then have to bootstrap the
67 autotools first:
69 $ autoreconf -i
71 Then the usual ./configure && make && make install will work.
73 There is a special makefile target make meta to bring several files (README,
74 AUTHORS, NEWS) in sync with the NoBug documentation wiki and update the
75 changelog.
77 What Is Installed
78 ~~~~~~~~~~~~~~~~~
80 Currently, NoBug installs the following:
82   * A single nobug.h headerfile which your code will use
83   * Two libs that are used by statically linking:
84       + 'libnobug.a' for singlethreaded programs.
85       + 'libnobugmt.a' for multithreaded programs.
87 Using NoBug
88 -----------
90 You can make NoBug features available either by installing it as described
91 above or by shipping the nobug sources along with your project.
93 To use NoBug, some controlling preprocessor macros have to be defined. The
94 nobug.h header should then be included.
96 A project using NoBug should use autoconf to check for execinfo.h and valgrind/
97 valgrind.h
99 AC_CHECK_HEADERS([execinfo.h valgrind/valgrind.h])
101 For Multithreaded programs, you should also check for pthread.h.
103 When the resulting HAVE_PTHREAD_H, HAVE_EXECINFO_H and HAVE_VALGRIND_VALGRIND_H
104 are defined by the configure script, the corresponding features become
105 available.
107 NoBug then defines 'NOBUG_USE_PTHREAD', 'NOBUG_USE_VALGRIND' and
108 'NOBUG_USE_EXECINFO' to 1. If you do not want to use any of these features in
109 NoBug, you can define these macros to 0 before including nobug.h.
111 If NVALGRIND is defined, valgrind support will not be available.
113 There are many other macros which can be set and overridden by the user to
114 control behavior. Please edit the wiki documentation if you find them useful.
116 To use NoBug with single threaded programmes, link libnobug.a to your project;
117 multi-threaded programmes should link with libnobugmt.a. The Library must be
118 initialized with NOBUG_INIT before any features can be used or a thread is
119 created. This is discussed in more detail at NoBug/Documentation/Macros/
120 MultiThreading.
122 Activating Logging
123 ~~~~~~~~~~~~~~~~~~
125 Checking for Additional Tools
126 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127 NoBug uses a number of additional optional tools depending on the application
128 and the debugging information required.  Such tools as valgrind, gdb and support
129 for multi-threaded applications can be tested whether they are available on a
130 particular system.  This can be done, for example, by using autoconf.  
132 Depending on the value of the following defines, the relevant tool or feature
133 is activated:
135     NOBUG_USE_VALGRIND::      
136         1;; Use valgrind
137         0;; Do not use valgrind
139     NOBUG_USE_PTHREAD::
140         1;; Support for multi-thread applications
141         0;; Single-threaded applications
143     NOBUG_USE_EXECINFO::
144         1;; Backtrace information
145         0;; No backtrace informatin
147 Header and Initialisation
148 ^^^^^^^^^^^^^^^^^^^^^^^^^
149 The project source file will have to include nobug.h, and Nobug will have to be
150 initialised using NOBUG_INIT before any NoBug features can be used.
152 -------------------------------------------------------
154 #include "nobug.h"
157 int main()
159     NOBUG_INIT();
160     ...
162 -------------------------------------------------------
165 Debugging Information Granuality: The Build Levels
166 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
167 Debugging information can be produced at three different levels: alpha, beta and
168 release:
170   ALPHA::
171         This debugging level is envisaged for the development phase of a project
172         where exhaustive testing and logging are requred.
173   BETA::
174         This debugging level is more appropriate for projects beyond the
175         development phase and ready for trials in the field and users willing to 
176         test the software.
177   RELEASE::
178         This level is for final, end-users. 
181 Select a Build Level
182 ++++++++++++++++++++
183 One of the above debugging levels is selected by defining one of the following:
185     *ALPHA*::   -DEBUG_ALPHA
187     *BETA*::    -DEBUG_BETA
189     *RELEASE*:: -DNDEBUG
191 Then the project is compiled.  If one of the above switches has not been set,
192 NoBug will complain.
194 Link Appropriate Library
195 ^^^^^^^^^^^^^^^^^^^^^^^^
196 Finally, the appropriate library (for either single or multi-threaded
197 applications) is linked to the project.
199    *libnobug.a*:: Link-in this library for single threaded applications.
200    *libnobugmt.a*:: Link with this library for multi-threaded applications.
203 Release builds remove all assertions, but some logging is still kept. We make
204 the assumption that bugs which were not covered in alpha and beta builds will
205 not easily show up in releases because the assertions there were not
206 sufficient. Furthermore, end users are not test bunnies and will not provide
207 good bug reports anyway. If there is a problem in a release build, try to track
208 down the cause using a beta build from the same source.
211 Scope Checks
212 ^^^^^^^^^^^^
213 The programmer can tag any scope as UNCHECKED or CHECKED. In ALPHA and BETA
214 builds, a global UNCHECKED is implied. In RELEASE builds, UNCHECKED scopes are
215 not allowed.
217 Test Matrix
218 ^^^^^^^^^^^
219 Here is a table of the basic assertions that are checked depending on the level
220 /scope combination:
222           ALPHA                          BETA                   RELEASE
223 UNCHECKED Preconditions, Postconditions, Preconditions,         compiling will
224           Invariants                     Postconditions         abort
225 CHECKED   Preconditions, Postconditions  Preconditions
227 Macros
228 ------
229 The NoBug interface is almost completely implemented using preprocessor macros.
230 This is required because NoBug uses the __FILE__ and __LINE__ macros to log
231 information on the current file and the current line number within that file.
232 Moreover, all the flat namespace uppercase identifiers make it ease to
233 recognise the macros in source code.
235 All macros are available without condition with the 'NOBUG' prefix. Macros are
236 also available without the NOBUG prefix as a convenience, however macros
237 without this prefix must not have been previously defined. All assertion and
238 logging macros have a corresponding form postfixed by '_DBG'. Such macros will
239 only be active within a debugger and are only available in ALPHA builds.
241 When NOBUG_DISABLE_SHORTNAMES is defined by the user, then only the NOBUG_
242 prefixed macros are available and the short forms will never be defined.
244 A set of macros are provided by NoBug that are postfixed by '_IF'. These macros
245 are wrappers around assert from the C lib. These macros have the following
246 form:
248   * WHATEVER_IF(when, ...)
250 We assert that when is true, if it is not, the assertion will fail. For
251 example:
253   * REQUIRE_IF(foo!=NULL, foo->something == constrained)
255 The assertion will only be performed if foo points to some memory, or is non
256 NULL.
258 Debugger versions are available using _IF_DBG postfixed to the name of the
259 macro.
261 Parameters types:
263 when    Assertion is only performed if expression 'when' is true at runtime
264 expr    Test without side effects
265 fmt     printf-like format string
266 ...     If not preceded by 'fmt', then printf-like format string; otherwise,
267         only its arguments
268 flag    Flag to enable custom logging groups
269 type    Data type to be checked as a single identifier name
270 pointer Pointer to type
271 lvl     Log level
272 depth   Depth for invariants and dumps
274 Initialization
276 Global init
278 You have to call
280   * NOBUG_INIT
282 before using any other NoBug feature. Probably in main or any other library
283 initialization routine. Calling NOBUG_INIT more than once is supported and each
284 subsequent call will be a no-op, thus initialization in main and in libraries
285 won't interfere.
287 Control Flags
289 If you want to use environment variable controlled debuging, then you have to
290 initialize each flag with
292   * NOBUG_INIT_FLAG(flagname)
296   * NOBUG_INIT_FLAG_LIMIT(flagname, default)
298 This is documented later in NoBug/Documentation/Macros/LoggingConfiguration.
300   * <!> These two macros call NOBUG_INIT for backward compatibility.
302 Threads
304 In Multithreaded programs you should assign an identifier to each thread after
305 it is created with
307   * NOBUG_THREAD_ID_SET(name)
309 If you don't call it, then NoBug will assign a automatic identifier. This is
310 documented in NoBug/Documentation/Macros/MultiThreading.
312 Assertions
314   * REQUIRE(expr, ...)
315       + Precondition (input) check. Use these macros to validate input a
316         function receives. The checks are enabled in ALPHA and BETA builds and
317         optimized out in RELEASE builds.
319     ENSURE(expr, ...)
320       + Postcondition (progress/output) check. Use these macros to validate the
321         data a function produces (example: return value). The checks enabled
322         unconditionally in ALPHA builds and optimized out in BETA builds for
323         scopes which are tagged as CHECKED. In RELEASE builds this checks are
324         always optimized out, but scopes tagged as UNCHECKED are not permitted.
326     ASSERT(expr, ...)
327       + Generic check. Use these macros when you want to validate something
328         which doesn't fall into one of the above categories. A example is when
329         a library function can return a unexpected result (scanf with syntax
330         error in the formatstring, when a constant/literal formatstring is
331         expected). The checks are enabled in ALPHA and BETA builds and
332         optimized out in RELEASE builds.
334     assert(expr)
335       + NoBug overrides the standard assert macro in ALPHA and BETA builds.
336         This is just a compatibility feature, its use is not suggested.
338     INVARIANT(type, pointer, depth)
339       + Checking invariants. You can provide more complex checking functions
340         which test the validity of datastructures. Invariants are only enabled
341         in ALPHA builds for scopes which are not tagged as CHECKED and
342         otherwise optimized out. (TODO: document how to write invariants)
344 Logging
346 Nearly all NoBug Macros emit some log message. NoBug gives the user fine
347 grained control over these log messages to display only interesting information
348 without loosing details.
350 Log messages are routed to different destinations which are:
352   * RINGBUFFER
353       + The underlying storage backend. Messages are appended to the end of the
354         buffer, overwriting older messages at the front of the buffer. NoBug
355         comes with a highly efficient ringbuffer implementation. This
356         ringbuffer is temporary by default but can be made persistent. NoBug
357         comes with a 'nobug_rbdump' tool to get a log out of such a ringbuffer.
358   * CONSOLE
359       + This is either just stderr or if running under valgrind then valgrind
360         facilities to include messages into its log will be used.
361   * FILE
362       + The user can open Files for log messages.
363   * SYSLOG
364       + Messages are send to the standard system logging daemon.
365   * APPLICATION
366       + There is a hook which allows the programmer to catch logmessages and
367         display them in a application defined way.
369 Each logmessage has a priority describing its severity in the same way as
370 syslog messages do.
372 All non-fatal messages are associated with a programmer defined flag describing
373 the source of the message (subsystem, module, ...).
375 Putting it all together: A user can define which source/flag shall be logged at
376 what priority level and to which destination. To make this all easier NoBug
377 tries to give reasonable defaults.
379 Configuration
381 Log Levels
383 Each Log macro has a explicit or implicit Log-Level which correspondends to
384 syslog levels. Logging is only emitted when the messages is more severe than a
385 defined limit.
387 The defaults look like:
389             ALPHA BETA    RELEASE
390 ringbuffer  TRACE INFO    NOTICE  ringbuffer must always be most verbose
391 console     INFO  NOTICE  -1      no log to console in release
392 file        TRACE NOTICE  WARNING
393 syslog      -1    NOTICE  WARNING no syslog for test runs
394 application INFO  WARNING ERROR
396 Depending on the build level there is a default logging target and a default
397 limit which is choosen when the user doesn't specify one.
399 The default limits are:
401   * In ALPHA builds, NOBUG_LOG_LIMIT_ALPHA is used which defaults to LOG_INFO
402   * In BETA builds, NOBUG_LOG_LIMIT_BETA is used and defaults to LOG_WARNING
403   * In RELEASE builds, NOBUG_LOG_LIMIT_RELEASE is used and defaults to LOG_CRIT
405 The default targets are:
407   * In ALPHA builds, NOBUG_LOG_TARGET_ALPHA is used which defaults to
408     NOBUG_TARGET_CONSOLE
409   * In BETA builds, NOBUG_LOG_TARGET_BETA is used and defaults to
410     NOBUG_TARGET_FILE
411   * In RELEASE builds, NOBUG_LOG_TARGET_RELEASE is used and defaults to
412     NOBUG_TARGET_SYSLOG
414 You can override all of those values with your own preference. Alternatively
415 NOBUG_LOG_LIMIT and NOBUG_LOG_TARGET can be defined by the user to override all
416 defaults.
418 Log Flags
420 Flags are used to tell NoBug about subsystems/modules or even finer grained
421 parts of the code.
423 A Flag should be declared with
425   * NOBUG_DECLARE_FLAG(flagname)
427 preferably in one of your headers
429 Further it must be defined with
431   * NOBUG_DEFINE_FLAG(flagname)
435   * NOBUG_DEFINE_FLAG_LIMIT(flagname, limit)
437 in one of your source files
439 There are also macros which take a 'parent' flag as parameter which is then
440 used to initialize the defaults from another flag
442   * NOBUG_DEFINE_FLAG_PARENT(flagname, parent)
446   * NOBUG_DEFINE_FLAG_PARENT_LIMIT(flagname, parent, limit)
448 This can be used to create hierachies of flags
450 Next you should call
452   * NOBUG_INIT_FLAG(flagname)
456   * NOBUG_INIT_FLAG_LIMIT(flagname, default)
458 once at the start of your program for every flag.
460 For flags defined with NOBUG_DEFINE_FLAG(flagname) the defaults are initialized
461 as in the table above, while NOBUG_DEFINE_FLAG_LIMIT(flagname, level) is used
462 to initialize the default target (depending on build level) to limit. Calling
463 NOBUG_INIT_FLAG(flagname) is optional for limit initialized flags.
465 NOBUG_INIT_FLAG(flagname) parses the environment variable '$NOBUG_LOG' for
466 flagname, the syntax is as following:
468 logdecl_list --> logdecl, any( ',' logdecl_list).
470 logdecl --> flag, opt(limitdecl, any(targetdecl))
472 flag --> "identifier of a flag"
474 limitdecl --> ':', "LIMITNAME"
476 targetdecl --> '@', "targetname", opt(targetopts)
478 targetopts --> '(', "options for target", ')', opt(targetopts)
480 Roughly speaking, NOBUG_LOG contains a comma separated list of declarations for
481 flags which are the name of the flag followed by a limit which is written in
482 all uppercase letters and preceeded by a colon, followed by target declarations
483 which are names of the targets, introduced by a at sign. Target declarations
484 can have options in future which is not yet implemented. Limit and target
485 declarations are optional and then choosen from the defaults table above. These
486 defaults are currently just an guess what should be useable and might be
487 redefined in future.
489 Options
491 The Following options are implemented:
493   * @ringbuffer
494       + (file=filename) set filename backing the ringbuffer
495         (size=nnn)      set size of the ringbuffer
496         (append)        don't erase existing ringbuffer
497         (keep)          keep file after application end
498         (temp)          unlink file instantly at creation
500     @console
501       + (fd=n) redirect console output to fd n
503     @file
504       + (name=filename) log to filename
505         (append)                        append to (existing) log
507     @syslog
508       + (ident=name) global prefix for syslog
509         (cons)       log to system console if syslog is down
510         (pid)        include pid in log
511         (perror)     log to stderr as well
513 Examples:
515 NOBUG_LOG='flag,other'                        # set the limit of the default target a default limit (see table above)
516 NOBUG_LOG='flag:DEBUG'                        # set the limit of the default target to DEBUG
517 NOBUG_LOG='flag:DEBUG@console@syslog'         # set console and syslog limits for flag to DEBUG
518 NOBUG_LOG='flag:DEBUG,other:TRACE@ringbuffer(file=log.rb)(size=8192)(keep)' # trace 'other' to a persistent ringbuffer
520 There is a predefined flag NOBUG_ON which is always enabled.
522 Example code:
524    1 #include "nobug.h"
525    2 NOBUG_DEFINE_FLAG (test);
526    3
527    4 int
528    5 main()
529    6 {
530    7   NOBUG_INIT_FLAG (test);
531    8
532    9   INFO (test, "Logging enabled");
533   10   INFO (NOBUG_ON, "Always on");
534   11 }
536 test it:
538 $ tcc -DEBUG_ALPHA -run example.c
539 example.c:10: debug: INFO: main: Always on
541 $ NOBUG_LOG=test tcc -DEBUG_ALPHA -run example.c
542 example.c:9: debug: INFO: main: Logging enabled
543 example.c:10: debug: INFO: main: Always on
545 C++ support
547 When used in C++ programms the following additional marocs are available:
549   * NOBUG_CPP_DEFINE_FLAG(name)
550     NOBUG_CPP_DEFINE_FLAG_PARENT(name, parent)
551     NOBUG_CPP_DEFINE_FLAG_LIMIT(name, default)
552     NOBUG_CPP_DEFINE_FLAG_PARENT_LIMIT(name, parent, default)
554 This macros statically initialize the flags at definition time, there is no
555 need to call NOBUG_INIT_FLAG().
557 The Logging Macros
559 These macros log with implicit Log Level, note that there are no more severe
560 levels than LOG_ERROR since these should be handled by Assertions in a
561 debugging library.
563   * ERROR(flag, fmt, ...)
564     ERROR_IF(expr, rflag, fmt, ...)
565       + Application takes a error handling brach
567     WARN(flag, fmt, ...)
568     WARN_IF(expr, flag, fmt, ...)
569       + Rare, handled but unexpected branch
571     INFO(flag, fmt, ...)
572     INFO_IF(expr, flag, fmt, ...)
573       + Message about program progress
575     NOTICE(flag, fmt, ...)
576     NOTICE_IF(expr, flag, fmt, ...)
577       + More detailed
579     TRACE(flag, fmt, ...)
580     TRACE_IF(expr, flag, fmt, ...)
581       + Very fine grained messages
583 Note that TRACE corresponds to LOG_DEBUG, using 'DEBUG' could be ambiguous.
585 There is one generic LOG macro which takes the level explicitly:
587   * LOG(flag, lvl, fmt, ...)
588     LOG_IF(expr, flag, lvl, fmt, ...)
590 Dumping Datastructures
592   * DUMP(flag, type, pointer, depth)
593       + Dump a datastructure
594     DUMP_IF(expr, flag, type, pointer, depth)
595       + Dump datastructure if expr is true
597 How to write DUMP handlers
599 if you have a
601    1 struct STRUCTNAME
602    2 {
603    3   int INTEGER_MEMBER;
604    4   char * STRING_MEMBER;
605    5   struct STRUCTNAME* next;
606    6 }
608 then you define a function like:
610    1 void
611    2 nobug_STRUCTNAME_dump (const struct STRUCTNAME* self,
612    3                        const int depth,
613    4                        const char* file,
614    5                        const int line,
615    6                        const char* func)
616    7 {
617    8   // check for self != NULL and that the depth
618    9   // limit did not exceed in recursive datastructures
619   10   if (self && depth)
620   11   {
621   12     // use DUMP_LOG not LOG to print the data
622   13     DUMP_LOG("STRUCTNAME %p: int is %d, string is %s", self,
623   14                              self->INTEGER_MEMBER,
624   15                              self->STRING_MEMBER);
625   16     // now recurse with decremented depth
626   17     nobug_STRUCTNAME_dump (self->next, depth-1, file, line, func);
627   18   }
628   19 }
630 now you can use the DUMP() macros within the code
632    1 example()
633    2 {
634    3   struct STRUCTNAME foo;
635    4   init(&foo);
636    5   DUMP (my_flag, STRUCTNAME, &foo, 2);
637    6 }
639 Dumping is by default done on level LOG_DEBUG, this can be overridden by
640 defining NOBUG_DUMP_LEVEL to some other level, further DUMP_IF is the only
641 enabled dumping macro for the RELEASE build level.
643 Source Annotations
645 One can tagging features as:
647   * DEPRECATED(...)
648       + Something which shouldn't be used in future.
649     UNIMPLEMENTED(...)
650       + important, not yet finished feature
651     PLANNED(...)
652       + planned for future feature
653     FIXME(...)
654       + known bug to be fixed later
655     TODO(...)
656       + enhancement to be done soon
657     NOTREACHED
658       + used to tag code-path which shall be never executed (defaults in switch
659         statements, else NOTREACHED after series of if's)
661 The advantage of this tagging over plain source comments is that we can take
662 some actions if we run in such a tag at compile or runtime:
664 the action to be taken when such a macro is hit depends on the build level:
666               ALPHA BETA         RELEASE
667 DEPRECATED    log   nothing      wont compile
668 UNIMPLEMENTED abort abort        wont compile
669 FIXME         log   wont compile wont compile
670 TODO          log   log          wont compile
671 PLANNED       log   nothing      nothing
672 NOTREACHED    abort abort        removed
674 Legend:
676   * abort means first log and then abort
677   * log will only log once for each sourceline (not on each hit)
678   * wont compile will abort compilation with a error message
679   * nothing optimized out, sane way
680   * removed optimized out for performance reasons
682 Resource Tracking
684 With little effort, NoBug can watch all kinds of resources a program uses. This
685 becomes useful for resources which are distributed over a multithreaded
686 program. Resource tracking is only active in ALPHA builds and optimized out in
687 BETA and RELEASE builds.
689 Concepts
691 Resources are abstracted, NoBug has little knowledge about the semantics of a
692 resource, it only keeps records of resources and the code using it and ensures
693 basic constraints. Detailed usage checks of resource have to be done with other
694 NoBug facilities.
696 Resources are identified by a arbitrary identifier which is just a pointer and
697 if using threads, NoBug's thread identifier. Additionally a name, the type and
698 the source locations which announced the resource are stored.
700 Code which wants to use a resource calls a enter macro with its own identifier
701 and state, then might alter the state and finally a leave macro when finished
702 with it.
704 When a resource is used one has to pass one of three states:
706   * NOBUG_RESOURCE_WAITING
707       + For resources where acquisition could block (locks) you enter it with a
708         WAITING state and as soon you aacquired it you change the state to one
709         of the following.
710   * NOBUG_RESOURCE_EXCLUSIVE
711       + Acquired the resource exclusively, this means for NoBug that trying to
712         get the resource again with the same identifier would be fatal, other
713         parts of the program could still enter it.
714   * NOBUG_RESOURCE_RECURSIVE
715       + The resource might be entered multiple times from the same identifier,
716         NoBug keeps a reference count and only deletes the record when the
717         resource is left as much times the state was changed to
718         NOBUG_RESOURCE_RECURSIVE
720 Possible state transitions:
722   * [ResourceTr]
724 The macros
726 Resources are accessed through handles, these handles are defined with
728   * RESOURCE_HANDLE(name)
730 This macro takes care that the declaration is optimized out in the same manner
731 the rest of the resource tracker would be disabled. You can still instantiate
732 handles as struct nobug_resource_record* in structures which must have a
733 constant size unconditional of the build level.
735 Resources are published by
737   * RESOURCE_ANNOUNCE(flag, type, name, identifier, handle)
739 Resources must be unique, it is a fatal error when a resource it tried to be
740 announced more than one time.
742   * 'flag' is nobug flag which turns logging on for this macro.
743   * 'type' is a cstring which should denote the domain of the resource,
744     examples are "file" "mutex" "lock" "database" and so on.
745   * 'name' is the actual name of a named resource this is a cstring which
746     together with type forms a unique identifier of the resource. 'type' and
747     'name' must be available through the entire lifetime of the resource, using
748     literal strings is recommended.
749   * 'identifier' is a pointer which should be unique for this resource, any
750     kind of pointer will suffice, it is only used for identification. In
751     multithreaded applications the thread identifier becomes an additional
752     identifier.
753   * 'handle' is a nobug_resource_record* which will be initialized to point to
754     the newly created resource.
756 When a resource becomes unavailable it is removed from the registry by
758   * RESOURCE_FORGET(flag, handle)
760 The resource must still exist and no users must be attached to it, else a fatal
761 error is raised.
763 Code which wants to use a resource attaches to it by
765   * RESOURCE_ENTER(flag, announced, name, identifier, state, handle)
766   * 'flag' is nobug flag which turns logging on for this macro.
767   * 'announced' is the handle set by RESOURCE_ANNOUNCE
768   * 'name' is a free-form identifier
769   * 'identifier' is some pointer which must be unique for the user of the
770     resource (see above)
771   * 'state' is the initial state, one of NOBUG_RESOURCE_WAITING,
772     NOBUG_RESOURCE_EXCLUSIVE or NOBUG_RESOURCE_RECURSIVE
773   * 'handle' is a nobug_resource_record* which will be initialized to the
774     entering node.
776 For some uses one can change the state with
778   * NOBUG_RESOURCE_STATE(flag, entered, state)
779   * 'flag' is nobug flag which turns logging on for this macro.
780   * 'entered' is the handle set by RESOURCE_ENTER
781   * 'state' is the new state Note that only certain state transitions are
782     allowed, see discussion/diagram above
784 When finished with using the resource you disconnect from it either with the
785 handle you initialized when entering it
787   * RESOURCE_LEAVE(flag, handle)
788   * 'flag' is nobug flag which turns logging on for this macro.
789   * 'handle' is the handle you got while entering the resource.
791 or by looking it up in the announced resource by its identifier
793   * RESOURCE_LEAVE_LOOKUP(flag, resource, identifier)
794   * 'flag' is nobug flag which turns logging on for this macro.
795   * 'resource' is the handle you got from announcing the resource.
796   * 'identifier' is the pointer you gave it when creating it
798 Resources keep track of the thread which used them, you cant ANNOUNCE/FORGET
799 ENTER/LEAVE the same handle from different threads.
801 Just a simple example:
803    1 NOBUG_DEFINE_FLAG_LIMIT(test, LOG_DEBUG);
804    2
805    3 void example()
806    4 {
807    5
808    6   // define a mutex and announce it
809    7   pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
810    8   RESOURCE_HANDLE(resource)
811    9   // 'example' is just a pointer to this function which suffices as unique id
812   10   RESOURCE_ANNOUNCE(test, "mutex", "my_mutex", example, resource);
813   11
814   12   // the following would be actually done in a different thread in a real program
815   13   RESOURCE_HANDLE(test, enter);                            // define a handle
816   14   RESOURCE_ENTER_NAME(test, resource, "example", &enter, NOBUG_RESOURCE_WAITING, enter);
817   15                                                            // announce that we want to use the resource
818   16                                                            // &enter also suffices as unique pointer
819   17   pthread_mutex_lock (&my_mutex);                          // this might block
820   18   RESOURCE_STATE(test, enter, NOBUG_RESOURCE_EXCLUSIVE);   // we got it, now announce that
821   19
822   20   // program does something useful here
823   21
824   22
825   23   pthread_mutex_lock (&my_mutex);                          // and instantly unlock
826   24   RESOURCE_LEAVE(test, enter);                             // we don't need it anymore
827   25
828   26   // back in the main thread
829   27   RESOURCE_FORGET(test, resource);                         // remove the resource from the public registry
830   28 }
832 Deadlock Detection
834 The Resource Tracker is able to detect potential deadlocks. This is done by
835 learning the relations between locks (precedence). A possible deadlock results
836 in a log message and a fatal abort. Note that only waiting on resources can
837 lead to a deadlock. Deadlock detection is implemented in the Resource Tracker
838 and active in ALPHA builds.
840 Logging Control
842 Unless the user defines NOBUG_RESOURCE_LOGGING to 0 each of the above macros
843 will emit a log message at NOBUG_RESOURCE_LOG_LEVEL which defaults to
844 LOG_DEBUG.
846 Notes
848 The Resource Tracker is neither bullet-proof nor exact. There are small race
849 conditions in the time we announce/forget/enter/remove resources and doing the
850 actual call to a resource. These race conditions affect the reporting exactness
851 and are a design decision, for there is no danger for practical use.
853 More important is that the Resource Tracker relies on that announce/forget and
854 enter/leave are properly paired. The programmer should ensure that this is done
855 right, else it will become unusable. This will be addressed in future NoBug
856 versions.
858 The underlying resource-tracking library may report errors, all these errors
859 are fatal for NoBug and trigger an abort(). When such an error occurs the
860 Resource Tracker is left in a locked state, which is harmless and intended for
861 generating reports prior the abort.
863 Multithreading
865 It is important that NoBug protects certain operations with locks in
866 multithreaded programs. You have to ensure that 'HAVE_PTHREAD_H' is defined by
867 the configuration system and use the 'libnobugmt.a' library for linking. It is
868 particular important that libraries using NoBug are compiled with
869 'HAVE_PTHREAD_H' enabled when they are intended to be used in multithreaded
870 programs.
872 When Multithreading is used, log messages contain a identifier of the
873 originating thread. This identifier should be set by
875   * NOBUG_THREAD_ID_SET(name)
877 right after thread creation. name is a string describing the purpose of the
878 thread. Nobug will assemble a unique identifier by appending a underscore and a
879 number to name, for example NOBUG_THREAD_ID_SET("gui") will result in a
880 identifier like "gui_5". When you don't set a thread identifier, then NoBug
881 assigns one automatically with the name 'thread' preprended if needed. Thread
882 identifiers are immutable once set.
884 For querying the thread identifier you use
886   * NOBUG_THREAD_ID_GET
888 which will return a const char* to the thread id in multithreaded programs and
889 a pointer to a literal "" in singlethreaded programs.
891 Tool Macros
893   * BACKTRACE(...)
894       + Log a stacktrace
895     ABORT
896       + just calls abort()
898 Best Practices
900 <!> this section is very work in progress
902 Workflow
904  1. Development
905       + Write a testsuite, build your program with -O0 -g -DEBUG_ALPHA and run
906         the testsuite under valgrind control. Hack until the program fits the
907         requirements defined by the testsuite.
908  2. Beta Test
909       + Build with desired optimization level and -g -DEBUG_BETA and give the
910         program to your beta testers.
911  3. Release
912       + Just build it with optimization and without -g -DEBUG_*
914 What and when to check
916   * Add REQUIRE checks on your interfaces (incoming parameters). Especially if
917     a argument might not cover the whole range of the underlying type.
918   * Don't waste your and your CPU's time with unnecessary checks. The testsuite
919     should validate your program. NoBug aids in debugging. You can add
920     Postconditions (ENSURE) and Invariants when you have a bug somewhere and
921     want to nail it down.
922   * Added checks don't need to be removed.
923   * When you use the CHECKED/UNCHECKED features then don't forget C scoping
924     rules, tag things as CHECKED from the leaves to the root.
926 Tips & Tricks
928   * TRACE(flagname) or TRACE_DBG(flagname) at the begin of every nontrivial
929     function will easily log the progress of your application.
930   * Trying a RELEASE build will abort on certain conditions (known BUG, TODO's,
931     UNCHECKED code), you can use this to find these spots.
933 This Documentation is maintained at:
935   * http://www.pipapo.org/pipawiki/NoBug/Documentation
937 NoBug/Documentation (last edited 2008-04-02 10:19:58 by 193)