Go to the previous, next section.
This document describes some of the common errors that occur with the use of ILU, and some techniques for dealing with them.
To use an interface with the Courier RPC protocol, a program number has to be specified
for each class. This is done with the program courier-register-interface
,
which assigns every class in the interface a program number and records the number in a database.
This database is searched by the runtime when a service or client attempts to export an instance
of that class. If the class is not registered in the appropriate database, you will see the
error message
_courier_FormProtocolHandle: Can't figure program#/version for class foo.bar.
courier-register-interface
will clean out old assignments to the classes not now named
in the interface, so you can run it as often as you like.
Our support for C++ currently depends on having the constructors for all
static instances run before main()
is called. If your compiler or interpreter
doesn't support that, you will experience odd behavior. The C++ language
does not strictly mandate that this initialization will be performed, but most compilers
seem to arrange things that way. We'd like to see how many compilers do not;
if your's doesn't, please send a note to [email protected]
telling us
what the compiler is.
ILU contains a number of trace statements that allow you to observe the progress of
certain operations within the ILU kernel. To enable these, you can set the environment
variable ILU_DEBUG
with the command
setenv ILU_DEBUG "xxx:yyy:zzz:..."
where xxx, yyy, and zzz are the names of various trace classes.
The classes are (as of May 1994) packet
, connection
,
incoming
, export
,
authentication
,
object
, sunrpc
, courier
, dcerpc
, call
,
tcp
, udp
, xnsspp
,
gc
, lock
, and server
. The special
class ALL
will enable all
trace statements: setenv ILU_DEBUG ALL
.
The function ilu_SetDebugLevelViaString(char *trace_classes)
may also be called from
an application program or debugger, to enable tracing. The argument trace_classes
should be formatted as described above.
ILU_DEBUG
may also be set to an unsigned integer value, where each bit set in the binary
version of the number corresponds to one of the above trace classes. For a list of the
various bit values, see the file `ilu/include/iluDebug.h'. Again, you can
also enable the tracing from a program or from a debugger, by calling the
routine ilu_SetDebugLevel(unsigned long trace_bits)
with an unsigned integer argument.
islscan
The islscan
program is supplied as part of the ILU
release. It runs the ISL parser against a file containing an
interface, and prints a "report" on the interface to standard output.
It can therefor be used to check the syntax of an interface before
running any language stubbers.
Report bugs (nah! -- couldn't be!) to the Internet address
[email protected]
, or to the XNS address
ILU-bugs:PARC:Xerox
. Bug reports are more helpful with some
information about the activity. General comments and suggestions can be
sent to either [email protected]
or ILU-bugs
.
gdb
When using ILU with C++ or C or even Common Lisp,
running under the GNU debugger gdb
can be helpful for
finding segmentation violations and other system errors. ILU provides a debugging trace
feature which can be set from gdb
with the following command:
(gdb) p ilu_SetDebugLevel(0xXXX) ilu_SetDebugLevel: setting debug mask from 0x0 to 0xXXX $1 = void (gdb)
The value XXX is an unsigned integer as discussed in section 3.
The debugger dbx
should also work.
The ILU error kernel distinguishes between two classes of fatal errors, which are errors that have no pre-coded recovery code. The first type of fatal error is a failure to allocate heap-allocated memory in a case where the caller has indicated that memory must be allocated. The second type of fatal error is the violation of a kernel invariant. The application using ILU can specify one of three failure actions to be taken when either of these fatal errors is encountered:
SEGV
signal by attempting to write to protected memory. This
is useful for generating core dumps for later study of the error.
sleep(3)
repeatedly. This option is useful
for keeping the process alive but dormant, so that a debugger can attach to it
and examine its "live" state. This is the default action.
An application can change the action taken on memory failures by
calling ilu_SetMemFaultAction
, and can change the action
taken on invariant violations by calling ilu_SetAssertionFailureAction
.
[ILU kernel]: void ilu_SetMemFaultAction ( int mfa )
Locking: unconstrained
Calling this tells the ILU kernel which drastic action is to be
performed when ilu_must_malloc
fails. -2 means to coredump;
-1 means to loop forever in repeated calls to sleep(3)
; positive numbers mean to exit(mfa)
.
The default is -1.
[ILU kernel]: void ilu_SetAssertionFailureAction ( int afa )
Locking: unconstrained
Calling this tells the ILU kernel which drastic action is to be
performed when a kernel invariant assertion fails. -2 means to coredump;
-1 means to loop forever in repeated calls to sleep(3)
; positive numbers mean to exit(afa)
.
The default is -1.
Go to the previous, next section.