xref: /freebsd-src/contrib/sendmail/libsm/assert.html (revision ee7b0571c2c18bdec848ed2044223cc88db29bd8)
140266059SGregory Neil Shapiro<html>
240266059SGregory Neil Shapiro<head>
340266059SGregory Neil Shapiro    <title> libsm : Assert and Abort </title>
440266059SGregory Neil Shapiro</head>
540266059SGregory Neil Shapiro<body>
640266059SGregory Neil Shapiro
740266059SGregory Neil Shapiro<a href="index.html">Back to libsm overview</a>
840266059SGregory Neil Shapiro
940266059SGregory Neil Shapiro<center>
1040266059SGregory Neil Shapiro    <h1> libsm : Assert and Abort </h1>
11*4313cc83SGregory Neil Shapiro    <br> $Id: assert.html,v 1.6 2001-08-27 21:47:03 ca Exp $
1240266059SGregory Neil Shapiro</center>
1340266059SGregory Neil Shapiro
1440266059SGregory Neil Shapiro<h2> Introduction </h2>
1540266059SGregory Neil Shapiro
1640266059SGregory Neil ShapiroThis package contains abstractions
1740266059SGregory Neil Shapirofor assertion checking and abnormal program termination.
1840266059SGregory Neil Shapiro
1940266059SGregory Neil Shapiro<h2> Synopsis </h2>
2040266059SGregory Neil Shapiro
2140266059SGregory Neil Shapiro<pre>
2240266059SGregory Neil Shapiro#include &lt;sm/assert.h&gt;
2340266059SGregory Neil Shapiro
2440266059SGregory Neil Shapiro/*
2540266059SGregory Neil Shapiro**  abnormal program termination
2640266059SGregory Neil Shapiro*/
2740266059SGregory Neil Shapiro
2840266059SGregory Neil Shapirovoid sm_abort_at(char *filename, int lineno, char *msg);
2940266059SGregory Neil Shapirotypedef void (*SM_ABORT_HANDLER)(char *filename, int lineno, char *msg);
3040266059SGregory Neil Shapirovoid sm_abort_sethandler(SM_ABORT_HANDLER);
3140266059SGregory Neil Shapirovoid sm_abort(char *fmt, ...)
3240266059SGregory Neil Shapiro
3340266059SGregory Neil Shapiro/*
3440266059SGregory Neil Shapiro**  assertion checking
3540266059SGregory Neil Shapiro*/
3640266059SGregory Neil Shapiro
3740266059SGregory Neil ShapiroSM_REQUIRE(expression)
3840266059SGregory Neil ShapiroSM_ASSERT(expression)
3940266059SGregory Neil ShapiroSM_ENSURE(expression)
4040266059SGregory Neil Shapiro
4140266059SGregory Neil Shapiroextern SM_DEBUG_T SmExpensiveRequire;
4240266059SGregory Neil Shapiroextern SM_DEBUG_T SmExpensiveAssert;
4340266059SGregory Neil Shapiroextern SM_DEBUG_T SmExpensiveEnsure;
4440266059SGregory Neil Shapiro
4540266059SGregory Neil Shapiro#if SM_CHECK_REQUIRE
4640266059SGregory Neil Shapiro#if SM_CHECK_ASSERT
4740266059SGregory Neil Shapiro#if SM_CHECK_ENSURE
4840266059SGregory Neil Shapiro
4940266059SGregory Neil Shapirocc -DSM_CHECK_ALL=0 -DSM_CHECK_REQUIRE=1 ...
5040266059SGregory Neil Shapiro</pre>
5140266059SGregory Neil Shapiro
5240266059SGregory Neil Shapiro<h2> Abnormal Program Termination </h2>
5340266059SGregory Neil Shapiro
5440266059SGregory Neil ShapiroThe functions sm_abort and sm_abort_at are used to report a logic
5540266059SGregory Neil Shapirobug and terminate the program.  They can be invoked directly,
5640266059SGregory Neil Shapiroand they are also used by the assertion checking macros.
5740266059SGregory Neil Shapiro
5840266059SGregory Neil Shapiro<dl>
5940266059SGregory Neil Shapiro<dt>
6040266059SGregory Neil Shapiro    void sm_abort_at(char *filename, int lineno, char *msg)
6140266059SGregory Neil Shapiro<dd>
6240266059SGregory Neil Shapiro	This is the low level interface for causing abnormal program
6340266059SGregory Neil Shapiro	termination.  It is intended to be invoked from a
6440266059SGregory Neil Shapiro	macro, such as the assertion checking macros.
6540266059SGregory Neil Shapiro
6640266059SGregory Neil Shapiro	If filename != NULL then filename and lineno specify the line
6740266059SGregory Neil Shapiro	of source code on which the logic bug is detected.  These
6840266059SGregory Neil Shapiro	arguments are normally either set to __FILE__ and __LINE__
6940266059SGregory Neil Shapiro	from an assertion checking macro, or they are set to NULL and 0.
7040266059SGregory Neil Shapiro
7140266059SGregory Neil Shapiro	The default action is to print an error message to smioerr
7240266059SGregory Neil Shapiro	using the arguments, and then call abort().  This default
7340266059SGregory Neil Shapiro	behaviour can be changed by calling sm_abort_sethandler.
7440266059SGregory Neil Shapiro<p>
7540266059SGregory Neil Shapiro<dt>
7640266059SGregory Neil Shapiro    void sm_abort_sethandler(SM_ABORT_HANDLER handler)
7740266059SGregory Neil Shapiro<dd>
7840266059SGregory Neil Shapiro	Install 'handler' as the callback function that is invoked
7940266059SGregory Neil Shapiro	by sm_abort_at.  This callback function is passed the same
8040266059SGregory Neil Shapiro	arguments as sm_abort_at, and is expected to log an error
8140266059SGregory Neil Shapiro	message and terminate the program.  The callback function should
8240266059SGregory Neil Shapiro	not raise an exception or perform cleanup: see Rationale.
8340266059SGregory Neil Shapiro
8440266059SGregory Neil Shapiro	sm_abort_sethandler is intended to be called once, from main(),
8540266059SGregory Neil Shapiro	before any additional threads are created: see Rationale.
8640266059SGregory Neil Shapiro	You should not use sm_abort_sethandler to
8740266059SGregory Neil Shapiro	switch back and forth between several handlers;
8840266059SGregory Neil Shapiro	this is particularly dangerous when there are
8940266059SGregory Neil Shapiro	multiple threads, or when you are in a library routine.
9040266059SGregory Neil Shapiro<p>
9140266059SGregory Neil Shapiro<dt>
9240266059SGregory Neil Shapiro    void sm_abort(char *fmt, ...)
9340266059SGregory Neil Shapiro<dd>
9440266059SGregory Neil Shapiro	This is the high level interface for causing abnormal program
9540266059SGregory Neil Shapiro	termination.  It takes printf arguments.  There is no need to
9640266059SGregory Neil Shapiro	include a trailing newline in the format string; a trailing newline
9740266059SGregory Neil Shapiro	will be printed if appropriate by the handler function.
9840266059SGregory Neil Shapiro</dl>
9940266059SGregory Neil Shapiro
10040266059SGregory Neil Shapiro<h2> Assertions </h2>
10140266059SGregory Neil Shapiro
10240266059SGregory Neil Shapiro    The assertion handling package
10340266059SGregory Neil Shapiro    supports a style of programming in which assertions are used
10440266059SGregory Neil Shapiro    liberally throughout the code, both as a form of documentation,
10540266059SGregory Neil Shapiro    and as a way of detecting bugs in the code by performing runtime checks.
10640266059SGregory Neil Shapiro<p>
10740266059SGregory Neil Shapiro    There are three kinds of assertion:
10840266059SGregory Neil Shapiro<dl>
10940266059SGregory Neil Shapiro<dt>
11040266059SGregory Neil Shapiro    SM_REQUIRE(expr)
11140266059SGregory Neil Shapiro<dd>
11240266059SGregory Neil Shapiro	This is an assertion used at the beginning of a function
11340266059SGregory Neil Shapiro	to check that the preconditions for calling the function
11440266059SGregory Neil Shapiro	have been satisfied by the caller.
11540266059SGregory Neil Shapiro<p>
11640266059SGregory Neil Shapiro<dt>
11740266059SGregory Neil Shapiro    SM_ENSURE(expr)
11840266059SGregory Neil Shapiro<dd>
11940266059SGregory Neil Shapiro	This is an assertion used just before returning from a function
12040266059SGregory Neil Shapiro	to check that the function has satisfied all of the postconditions
12140266059SGregory Neil Shapiro	that it is required to satisfy by its contract with the caller.
12240266059SGregory Neil Shapiro<p>
12340266059SGregory Neil Shapiro<dt>
12440266059SGregory Neil Shapiro    SM_ASSERT(expr)
12540266059SGregory Neil Shapiro<dd>
12640266059SGregory Neil Shapiro	This is an assertion that is used in the middle of a function,
12740266059SGregory Neil Shapiro	to check loop invariants, and for any other kind of check that is
12840266059SGregory Neil Shapiro	not a "require" or "ensure" check.
12940266059SGregory Neil Shapiro</dl>
13040266059SGregory Neil Shapiro    If any of the above assertion macros fail, then sm_abort_at
13140266059SGregory Neil Shapiro    is called.  By default, a message is printed to stderr and the
13240266059SGregory Neil Shapiro    program is aborted.  For example, if SM_REQUIRE(arg &gt; 0) fails
13340266059SGregory Neil Shapiro    because arg &lt;= 0, then the message
13440266059SGregory Neil Shapiro<blockquote><pre>
13540266059SGregory Neil Shapirofoo.c:47: SM_REQUIRE(arg &gt; 0) failed
13640266059SGregory Neil Shapiro</pre></blockquote>
13740266059SGregory Neil Shapiro    is printed to stderr, and abort() is called.
13840266059SGregory Neil Shapiro    You can change this default behaviour using sm_abort_sethandler.
13940266059SGregory Neil Shapiro
14040266059SGregory Neil Shapiro<h2> How To Disable Assertion Checking At Compile Time </h2>
14140266059SGregory Neil Shapiro
14240266059SGregory Neil Shapiro    You can use compile time macros to selectively enable or disable
14340266059SGregory Neil Shapiro    each of the three kinds of assertions, for performance reasons.
14440266059SGregory Neil Shapiro    For example, you might want to enable SM_REQUIRE checking
14540266059SGregory Neil Shapiro    (because it finds the most bugs), but disable the other two types.
14640266059SGregory Neil Shapiro<p>
14740266059SGregory Neil Shapiro    By default, all three types of assertion are enabled.
14840266059SGregory Neil Shapiro    You can selectively disable individual assertion types
14940266059SGregory Neil Shapiro    by setting one or more of the following cpp macros to 0
15040266059SGregory Neil Shapiro    before &lt;sm/assert.h&gt; is included for the first time:
15140266059SGregory Neil Shapiro<blockquote>
15240266059SGregory Neil Shapiro	SM_CHECK_REQUIRE<br>
15340266059SGregory Neil Shapiro	SM_CHECK_ENSURE<br>
15440266059SGregory Neil Shapiro	SM_CHECK_ASSERT<br>
15540266059SGregory Neil Shapiro</blockquote>
15640266059SGregory Neil Shapiro    Or, you can define SM_CHECK_ALL as 0 to disable all assertion
15740266059SGregory Neil Shapiro    types, then selectively define one or more of SM_CHECK_REQUIRE,
15840266059SGregory Neil Shapiro    SM_CHECK_ENSURE or SM_CHECK_ASSERT as 1.  For example,
15940266059SGregory Neil Shapiro    to disable all assertions except for SM_REQUIRE, you can use
16040266059SGregory Neil Shapiro    these C compiler flags:
16140266059SGregory Neil Shapiro<blockquote>
16240266059SGregory Neil Shapiro	-DSM_CHECK_ALL=0 -DSM_CHECK_REQUIRE=1
16340266059SGregory Neil Shapiro</blockquote>
16440266059SGregory Neil Shapiro
16540266059SGregory Neil Shapiro    After &lt;sm/assert.h&gt; is included, the macros
16640266059SGregory Neil Shapiro    SM_CHECK_REQUIRE, SM_CHECK_ENSURE and SM_CHECK_ASSERT
16740266059SGregory Neil Shapiro    are each set to either 0 or 1.
16840266059SGregory Neil Shapiro
16940266059SGregory Neil Shapiro<h2> How To Write Complex or Expensive Assertions </h2>
17040266059SGregory Neil Shapiro
17140266059SGregory Neil Shapiro    Sometimes an assertion check requires more code than a simple
17240266059SGregory Neil Shapiro    boolean expression.
17340266059SGregory Neil Shapiro    For example, it might require an entire statement block
17440266059SGregory Neil Shapiro    with its own local variables.
17540266059SGregory Neil Shapiro    You can code such assertion checks by making them conditional on
17640266059SGregory Neil Shapiro    SM_CHECK_REQUIRE, SM_CHECK_ENSURE or SM_CHECK_ASSERT,
17740266059SGregory Neil Shapiro    and using sm_abort to signal failure.
17840266059SGregory Neil Shapiro<p>
17940266059SGregory Neil Shapiro    Sometimes an assertion check is significantly more expensive
18040266059SGregory Neil Shapiro    than one or two comparisons.
18140266059SGregory Neil Shapiro    In such cases, it is not uncommon for developers to comment out
18240266059SGregory Neil Shapiro    the assertion once the code is unit tested.
18340266059SGregory Neil Shapiro    Please don't do this: it makes it hard to turn the assertion
18440266059SGregory Neil Shapiro    check back on for the purposes of regression testing.
18540266059SGregory Neil Shapiro    What you should do instead is make the assertion check conditional
18640266059SGregory Neil Shapiro    on one of these predefined debug objects:
18740266059SGregory Neil Shapiro<blockquote>
18840266059SGregory Neil Shapiro	SmExpensiveRequire<br>
18940266059SGregory Neil Shapiro	SmExpensiveAssert<br>
19040266059SGregory Neil Shapiro	SmExpensiveEnsure
19140266059SGregory Neil Shapiro</blockquote>
19240266059SGregory Neil Shapiro    By doing this, you bring the cost of the assertion checking code
19340266059SGregory Neil Shapiro    back down to a single comparison, unless expensive assertion checking
19440266059SGregory Neil Shapiro    has been explicitly enabled.
19540266059SGregory Neil Shapiro    By the way, the corresponding debug category names are
19640266059SGregory Neil Shapiro<blockquote>
19740266059SGregory Neil Shapiro	sm_check_require<br>
19840266059SGregory Neil Shapiro	sm_check_assert<br>
19940266059SGregory Neil Shapiro	sm_check_ensure
20040266059SGregory Neil Shapiro</blockquote>
20140266059SGregory Neil Shapiro    What activation level should you check for?
20240266059SGregory Neil Shapiro    Higher levels correspond to more expensive assertion checks.
20340266059SGregory Neil Shapiro    Here are some basic guidelines:
20440266059SGregory Neil Shapiro<blockquote>
20540266059SGregory Neil Shapiro	level 1: &lt; 10 basic C operations<br>
20640266059SGregory Neil Shapiro	level 2: &lt; 100 basic C operations<br>
20740266059SGregory Neil Shapiro	level 3: &lt; 1000 basic C operations<br>
20840266059SGregory Neil Shapiro	...
20940266059SGregory Neil Shapiro</blockquote>
21040266059SGregory Neil Shapiro
21140266059SGregory Neil Shapiro<p>
21240266059SGregory Neil Shapiro    Here's a contrived example of both techniques:
21340266059SGregory Neil Shapiro<blockquote><pre>
21440266059SGregory Neil Shapirovoid
21540266059SGregory Neil Shapirow_munge(WIDGET *w)
21640266059SGregory Neil Shapiro{
21740266059SGregory Neil Shapiro    SM_REQUIRE(w != NULL);
21840266059SGregory Neil Shapiro#if SM_CHECK_REQUIRE
21940266059SGregory Neil Shapiro    /*
22040266059SGregory Neil Shapiro    **  We run this check at level 3 because we expect to check a few hundred
22140266059SGregory Neil Shapiro    **  table entries.
22240266059SGregory Neil Shapiro    */
22340266059SGregory Neil Shapiro
22440266059SGregory Neil Shapiro    if (sm_debug_active(&SmExpensiveRequire, 3))
22540266059SGregory Neil Shapiro    {
22640266059SGregory Neil Shapiro        int i;
22740266059SGregory Neil Shapiro
22840266059SGregory Neil Shapiro        for (i = 0; i &lt; WIDGET_MAX; ++i)
22940266059SGregory Neil Shapiro        {
23040266059SGregory Neil Shapiro            if (w[i] == NULL)
23140266059SGregory Neil Shapiro                sm_abort("w_munge: NULL entry %d in widget table", i);
23240266059SGregory Neil Shapiro        }
23340266059SGregory Neil Shapiro    }
23440266059SGregory Neil Shapiro#endif /* SM_CHECK_REQUIRE */
23540266059SGregory Neil Shapiro</pre></blockquote>
23640266059SGregory Neil Shapiro
23740266059SGregory Neil Shapiro<h2> Other Guidelines </h2>
23840266059SGregory Neil Shapiro
23940266059SGregory Neil Shapiro    You should resist the urge to write SM_ASSERT(0) when the code has
24040266059SGregory Neil Shapiro    reached an impossible place.  It's better to call sm_abort, because
24140266059SGregory Neil Shapiro    then you can generate a better error message.  For example,
24240266059SGregory Neil Shapiro<blockquote><pre>
24340266059SGregory Neil Shapiroswitch (foo)
24440266059SGregory Neil Shapiro{
24540266059SGregory Neil Shapiro    ...
24640266059SGregory Neil Shapiro  default:
24740266059SGregory Neil Shapiro    sm_abort("impossible value %d for foo", foo);
24840266059SGregory Neil Shapiro}
24940266059SGregory Neil Shapiro</pre></blockquote>
25040266059SGregory Neil Shapiro    Note that I did not bother to guard the default clause of the switch
25140266059SGregory Neil Shapiro    statement with #if SM_CHECK_ASSERT ... #endif, because there is
25240266059SGregory Neil Shapiro    probably no performance gain to be had by disabling this particular check.
25340266059SGregory Neil Shapiro<p>
25440266059SGregory Neil Shapiro    Avoid including code that has side effects inside of assert macros,
25540266059SGregory Neil Shapiro    or inside of SM_CHECK_* guards.  You don't want the program to stop
25640266059SGregory Neil Shapiro    working if assertion checking is disabled.
25740266059SGregory Neil Shapiro
25840266059SGregory Neil Shapiro<h2> Rationale for Logic Bug Handling </h2>
25940266059SGregory Neil Shapiro
26040266059SGregory Neil Shapiro    When a logic bug is detected, our philosophy is to log an error message
26140266059SGregory Neil Shapiro    and terminate the program, dumping core if possible.
26240266059SGregory Neil Shapiro    It is not a good idea to raise an exception, attempt cleanup,
26340266059SGregory Neil Shapiro    or continue program execution.  Here's why.
26440266059SGregory Neil Shapiro<p>
26540266059SGregory Neil Shapiro    First of all, to facilitate post-mortem analysis, we want to dump core
26640266059SGregory Neil Shapiro    on detecting a logic bug, disturbing the process image as little as
26740266059SGregory Neil Shapiro    possible before dumping core.  We don't want to raise an exception
26840266059SGregory Neil Shapiro    and unwind the stack, executing cleanup code, before dumping core,
26940266059SGregory Neil Shapiro    because that would obliterate information we need to analyze the cause
27040266059SGregory Neil Shapiro    of the abort.
27140266059SGregory Neil Shapiro<p>
27240266059SGregory Neil Shapiro    Second, it is a bad idea to raise an exception on an assertion failure
27340266059SGregory Neil Shapiro    because this places unacceptable restrictions on code that uses
27440266059SGregory Neil Shapiro    the assertion macros.
27540266059SGregory Neil Shapiro    The reason is this: the sendmail code must be written so that
27640266059SGregory Neil Shapiro    anywhere it is possible for an assertion to be raised, the code
27740266059SGregory Neil Shapiro    will catch the exception and clean up if necessary, restoring
27840266059SGregory Neil Shapiro    data structure invariants and freeing resources as required.
27940266059SGregory Neil Shapiro    If an assertion failure was signalled by raising an exception,
28040266059SGregory Neil Shapiro    then every time you added an assertion, you would need to check
28140266059SGregory Neil Shapiro    both the function containing the assertion and its callers to see
28240266059SGregory Neil Shapiro    if any exception handling code needed to be added to clean up properly
28340266059SGregory Neil Shapiro    on assertion failure.  That is far too great a burden.
28440266059SGregory Neil Shapiro<p>
28540266059SGregory Neil Shapiro    It is a bad idea to attempt cleanup upon detecting a logic bug
28640266059SGregory Neil Shapiro    for several reasons:
28740266059SGregory Neil Shapiro<ul>
28840266059SGregory Neil Shapiro<li>If you need to perform cleanup actions in order to preserve the
28940266059SGregory Neil Shapiro    integrity of the data that the program is handling, then the
29040266059SGregory Neil Shapiro    program is not fault tolerant, and needs to be redesigned.
29140266059SGregory Neil Shapiro    There are several reasons why a program might be terminated unexpectedly:
29240266059SGregory Neil Shapiro    the system might crash, the program might receive a signal 9,
29340266059SGregory Neil Shapiro    the program might be terminated by a memory fault (possibly as a
29440266059SGregory Neil Shapiro    side effect of earlier data structure corruption), and the program
29540266059SGregory Neil Shapiro    might detect a logic bug and terminate itself.  Note that executing
29640266059SGregory Neil Shapiro    cleanup actions is not feasible in most of the above cases.
29740266059SGregory Neil Shapiro    If the program has a fault tolerant design, then it will not lose
29840266059SGregory Neil Shapiro    data even if the system crashes in the middle of an operation.
29940266059SGregory Neil Shapiro<p>
30040266059SGregory Neil Shapiro<li>If the cause of the logic bug is earlier data structure corruption,
30140266059SGregory Neil Shapiro    then cleanup actions intended to preserve the integrity of the data
30240266059SGregory Neil Shapiro    that the program is handling might cause more harm than good: they
30340266059SGregory Neil Shapiro    might cause information to be corrupted or lost.
30440266059SGregory Neil Shapiro<p>
30540266059SGregory Neil Shapiro<li>If the program uses threads, then cleanup is much more problematic.
30640266059SGregory Neil Shapiro    Suppose that thread A is holding some locks, and is in the middle of
30740266059SGregory Neil Shapiro    modifying a shared data structure.  The locks are needed because the
30840266059SGregory Neil Shapiro    data structure is currently in an inconsistent state.  At this point,
30940266059SGregory Neil Shapiro    a logic bug is detected deep in a library routine called by A.
31040266059SGregory Neil Shapiro    How do we get all of the running threads to stop what they are doing
31140266059SGregory Neil Shapiro    and perform their thread-specific cleanup actions before terminating?
31240266059SGregory Neil Shapiro    We may not be able to get B to clean up and terminate cleanly until
31340266059SGregory Neil Shapiro    A has restored the invariants on the data structure it is modifying
31440266059SGregory Neil Shapiro    and releases its locks.  So, we raise an exception and unwind the stack,
31540266059SGregory Neil Shapiro    restoring data structure invariants and releasing locks at each level
31640266059SGregory Neil Shapiro    of abstraction, and performing an orderly shutdown.  There are certainly
31740266059SGregory Neil Shapiro    many classes of error conditions for which using the exception mechanism
31840266059SGregory Neil Shapiro    to perform an orderly shutdown is appropriate and feasible, but there
31940266059SGregory Neil Shapiro    are also classes of error conditions for which exception handling and
32040266059SGregory Neil Shapiro    orderly shutdown is dangerous or impossible.  The abnormal program
32140266059SGregory Neil Shapiro    termination system is intended for this second class of error conditions.
32240266059SGregory Neil Shapiro    If you want to trigger orderly shutdown, don't call sm_abort:
32340266059SGregory Neil Shapiro    raise an exception instead.
32440266059SGregory Neil Shapiro</ul>
32540266059SGregory Neil Shapiro<p>
32640266059SGregory Neil Shapiro    Here is a strategy for making sendmail fault tolerant.
32740266059SGregory Neil Shapiro    Sendmail is structured as a collection of processes.  The "root" process
32840266059SGregory Neil Shapiro    does as little as possible, except spawn children to do all of the real
32940266059SGregory Neil Shapiro    work, monitor the children, and act as traffic cop.
33040266059SGregory Neil Shapiro    We use exceptions to signal expected but infrequent error conditions,
33140266059SGregory Neil Shapiro    so that the process encountering the exceptional condition can clean up
33240266059SGregory Neil Shapiro    and keep going.  (Worker processes are intended to be long lived, in
33340266059SGregory Neil Shapiro    order to minimize forking and increase performance.)  But when a bug
33440266059SGregory Neil Shapiro    is detected in a sendmail worker process, the worker process does minimal
33540266059SGregory Neil Shapiro    or no cleanup and then dies.  A bug might be detected in several ways:
33640266059SGregory Neil Shapiro    the process might dereference a NULL pointer, receive a signal 11,
33740266059SGregory Neil Shapiro    core dump and die, or an assertion might fail, in which case the process
33840266059SGregory Neil Shapiro    commits suicide.  Either way, the root process detects the death of the
33940266059SGregory Neil Shapiro    worker, logs the event, and spawns another worker.
34040266059SGregory Neil Shapiro
34140266059SGregory Neil Shapiro<h2> Rationale for Naming Conventions </h2>
34240266059SGregory Neil Shapiro
34340266059SGregory Neil Shapiro    The names "require" and "ensure" come from the writings of Bertrand Meyer,
34440266059SGregory Neil Shapiro    a prominent evangelist for assertion checking who has written a number of
34540266059SGregory Neil Shapiro    papers about the "Design By Contract" programming methodology,
34640266059SGregory Neil Shapiro    and who created the Eiffel programming language.
34740266059SGregory Neil Shapiro    Many other assertion checking packages for C also have "require" and
34840266059SGregory Neil Shapiro    "ensure" assertion types.  In short, we are conforming to a de-facto
34940266059SGregory Neil Shapiro    standard.
35040266059SGregory Neil Shapiro<p>
35140266059SGregory Neil Shapiro    We use the names <tt>SM_REQUIRE</tt>, <tt>SM_ASSERT</tt>
35240266059SGregory Neil Shapiro    and <tt>SM_ENSURE</tt> in preference to to <tt>REQUIRE</tt>,
35340266059SGregory Neil Shapiro    <tt>ASSERT</tt> and <tt>ENSURE</tt> because at least two other
35440266059SGregory Neil Shapiro    open source libraries (libisc and libnana) define <tt>REQUIRE</tt>
35540266059SGregory Neil Shapiro    and <tt>ENSURE</tt> macros, and many libraries define <tt>ASSERT</tt>.
35640266059SGregory Neil Shapiro    We want to avoid name conflicts with other libraries.
35740266059SGregory Neil Shapiro
35840266059SGregory Neil Shapiro</body>
35940266059SGregory Neil Shapiro</html>
360