Error handlers

ErrorHandler

All Click error messages are passed to an instance of the ErrorHandler class. ErrorHandler separates the generation of error messages from the particular way those messages should be printed. It also makes it easy to automatically decorate errors with context information. Most Click users must know how to report errors to an ErrorHandler, and how ErrorHandlers count the messages they receive. This section also describes how to decorate error messages with error veneers, and how to write new ErrorHandlers. ErrorHandler and its important subclasses are defined in <click/error.hh>.

Class Initialization

The ErrorHandler class maintains some global state that must be initialized by calling static_initialize at the beginning of the program, and may be freed by calling static_cleanup when execution is complete.

void static_initialize (ErrorHandler *default_errh) Static Method on ErrorHandler

Call this function exactly once, at the beginning of the program, before any error messages are reported to any ErrorHandler. It is OK to create arbitrary ErrorHandler objects before calling this method, however. The default_errh argument becomes the default ErrorHandler; see Basic ErrorHandlers.

void static_cleanup () Static Method on ErrorHandler

Call this function exactly once, just before the program exits. Destroys the default and silent ErrorHandlers and cleans up other ErrorHandler-related memory. It is an error to call any ErrorHandler method after calling static_cleanup.

Reporting Errors

ErrorHandler's basic error reporting methods take a format string, which may use printf-like % escape sequences, and additional arguments as required by the format string. See Error Format Strings, for more details on the format string. The five methods differ in the seriousness of the error they report.

void debug (const char *format, ...) Method on ErrorHandler

void message (const char *format, ...) Method on ErrorHandler

int warning (const char *format, ...) Method on ErrorHandler

int error (const char *format, ...) Method on ErrorHandler

int fatal (const char *format, ...) Method on ErrorHandler

Report the error described by format and any additional arguments. The methods are listed by increasing seriousness. Use debug for debugging messages that should not be printed in a production environment; message for explanatory messages that do not indicate errors; warning for warnings (this function prepends the string warning: to every line of the error message); error for errors; and fatal for errors so serious that they should halt the execution of the program. The three functions that indicate errors, warning, error, and fatal, always return -EINVAL. In some environments, fatal will actually exit the program with exit code 1.

Each of these methods has an analogue that additionally takes a landmark: a string representing where the error took place. A typical landmark contains a file name and line number, separated by a colon--foo.click:31, for example.

void ldebug (const String &landmark, const char *format, ...) Method on ErrorHandler

void lmessage (const String &landmark, const char *format, ...) Method on ErrorHandler

int lwarning (const String &landmark, const char *format, ...) Method on ErrorHandler

int lerror (const String &landmark, const char *format, ...) Method on ErrorHandler

int lfatal (const String &landmark, const char *format, ...) Method on ErrorHandler

Report the error described by format and any additional arguments. The error took place at landmark. Most ErrorHandlers will simply prepend landmark: to each line of the error message.

These methods are all implemented as wrappers around the verror function. This function takes a landmark, a format string, a va_list packaging up any additional arguments, and a seriousness value, which encodes how serious the error was. The Seriousness enumerated type, which is defined in the ErrorHandler class, represents seriousness values. There are five constants, corresponding to the five error-reporting methods:

  • ERR_DEBUG Corresponds to debug and ldebug.
  • ERR_MESSAGE Corresponds to message and lmessage.
  • ERR_WARNING Corresponds to warning and lwarning.
  • ERR_ERROR Corresponds to error and lerror.
  • ERR_FATAL Corresponds to fatal and lfatal.

int verror (Seriousness seriousness, const String &landmark, const char *format, va_list val) Method on ErrorHandler

Report the error described by format and val. The error took place at landmark, if landmark is nonempty. The seriousness value is one of the five constants described above. Always returns -EINVAL.

Format Strings

ErrorHandler's format strings closely follow C's standard printf format strings. Most characters in the format string are printed verbatim. The % character introduces a conversion, which prints data read from the remaining arguments. The format string may contain newlines \n, but it need not end with a newline; ErrorHandler will add a final newline if one does not exist.

Each conversion, or formatting escape, follows this pattern:

  • First, the % character introduces each conversion.
  • Next comes zero or more flag characters;
  • then an optional field width;
  • then an optional precision;
  • then an optional length modifier;
  • and finally, the mandatory conversion specifier, which is usually a single character, but may be a name enclosed in braces.

We discuss each of these is turn. Any conversion may be modified by zero or more of these flag characters.

#

The value should be converted to an "alternate form". For o conversions, the first character of the output string is made 0, by prepending a 0 if there was not one already. For x and X conversions, nonzero values have 0x or 0X prepended, respectively.

0

The value should be zero padded. For d, i, u, o, x, and X conversions, the converted value is padded on the left with 0 characters rather than spaces. -

The value should be left-justified within the field width.

(a space)

Leave a blank before a nonnegative number produced by a signed conversion.

+

Print a + character before a nonnegative number produced by a signed conversion.

The optional field width, a decimal digit string, forces the conversion to use a minimum number of characters. The result of a conversion is padded on the left with space characters to reach the minimum field width, unless one of the 0 or - flags was supplied.

The optional precision is a decimal digit string preceded by a period .. For d, i, u, o, x, and X conversions, the precision specifies the minimum number of digits that must appear; results with fewer digits are padded on the left with 0 characters. For the s conversion, the precision specifies the maximum number of characters that can be printed. For e, f, E, and F conversions, it specifies the number of digits to appear after the radix character; for g and G conversions, the number of significant digits.

If either the field width or precision is specified as a star *, ErrorHandler reads the next argument as an integer and uses that instead.

Length modifiers affect the argument type read by the conversion. There are three modifiers:

h The next argument is a short or unsigned short. Affects the d, i, u, o, x, and X conversions.

l

The next argument is a long or unsigned long. Affects the d, i, u, o, x, and X conversions.

ll

The next argument is a long long or unsigned long long. Affects the d, i, u, o, x, and X conversions.

Finally, these are the conversions themselves.

s

Print the const char * argument, treated as a C string.

c

The int argument is treated as a character constant. Printable ASCII characters (values between 32 and 126) are printed verbatim. Characters \n, \t, \r, and \0 use those C escape representations. Other characters use the representation \%03o.

d, i

The argument is an int; print its decimal representation.

u

The argument is an unsigned int; print its decimal representation.

o

The argument is an unsigned int; print its octal representation.

x, X

The argument is an unsigned int; print its hexadecimal representation. The %x conversion uses lowercase letters; %X uses uppercase letters.

e, f, g, E, F, G

The argument is a double; print its representation as if by printf (user-level drivers only).

p

The void * argument is cast to unsigned long and printed as by %#lx.

%

Print a literal % character.

{element}

The argument is an Element *. Print that element's declaration.

Note that ErrorHandler does not support the n conversion.

Counting Errors

ErrorHandler objects count the number of errors and warnings they have received and make those values available to the user.

virtual int nwarnings () const Method on ErrorHandler

virtual int nerrors () const Method on ErrorHandler

Returns the number of warnings or errors received by this ErrorHandler so far.

virtual void reset_counts () Method on ErrorHandler

Resets the nwarnings and nerrors counters to zero.

These counters are typically used to determine whether an error has taken place in some complex piece of code. For example:

int before_nerrors = errh->nerrors(); ... complex code that may report errors to errh ... if (errh->nerrors() != before_nerrors) { an error has taken place }

   

Basic ErrorHandlers

Every Click error message eventually reaches some basic ErrorHandler, which generally prints the messages it receives. The user-level driver's basic ErrorHandler prints error messages to standard error, while in the Linux kernel module, the basic ErrorHandler logs messages to the syslog and stores them for access via /proc/click/errors.

Two basic ErrorHandlers are always accessible via static methods: the default ErrorHandler, returned by default_handler and set by set_default_handler; and the silent ErrorHandler, returned by silent_handler, which ignores any error messages it receives.

ErrorHandler * default_handler () Static Method on ErrorHandler

Returns the default ErrorHandler.

void set_default_handler (ErrorHandler *errh) Static Method on ErrorHandler

Sets the default ErrorHandler to errh. The static_initialize method also sets the default ErrorHandler; see ErrorHandler Initialization.

ErrorHandler * silent_handler () Static Method on ErrorHandler

Returns the silent ErrorHandler. This handler ignores any error messages it receives. It maintains correct nwarnings and nerrors counts, however.

FileErrorHandler, a kind of basic ErrorHandler, is available in any user-level program. It prints every message it receives to some file, usually standard error. It can also prepend an optional context string to every line of every error message.

FileErrorHandler (FILE *f, const String &prefix = "") Constructor on FileErrorHandler

Constructs a FileErrorHandler that prints error messages to file f. If prefix is nonempty, then every line of every error message is prepended by prefix.

Error Veneers

Error veneers wrap around basic ErrorHandler objects and change how error text is generated. An error veneer generally changes each error message's text in some way, perhaps by adding a context message or some indentation. It then passes the altered text to the basic ErrorHandler for printing. Error veneers can be easily nested.

The first argument to each error veneer constructor is a pointer to another ErrorHandler object. The veneer will pass altered error text to this handler, the base handler, for further processing and printing. It also delegates nwarnings() and nerrors() calls to the base handler.

Click comes with three error veneers: one for adding context, one for prepending text to every line, and one for supplying missing landmarks. It is easy to write others; see Writing ErrorHandlers, for details. ContextErrorHandler (ErrorHandler *base_errh, const String &context, const String &indent = " ") Constructor on ContextErrorHandler

Constructs a ContextErrorHandler with base_errh as base. The first time this handler receives an error message, it will precede the message with the context string--generally more detailed information about where the error has occurred. Every line in every received error message is prepended with indent, two spaces by default, to set off the message from its context.

PrefixErrorHandler (ErrorHandler *base_errh, const String &prefix) Constructor on PrefixErrorHandler

Constructs a PrefixErrorHandler with base_errh as base. This handler precedes every line of every error message with prefix.

LandmarkErrorHandler (ErrorHandler *base_errh, const String &landmark) Constructor on LandmarkErrorHandler

Constructs a LandmarkErrorHandler with base_errh as base. This handler supplies landmark in place of any blank landmark passed to it. This will cause the base handler to include landmark in its error message.

To demonstrate these veneers in practice, we'll use the following function, which prints two error messages:

void f(ErrorHandler *errh) { errh->error("First line\nSecond line"); errh->lwarning("here", "Third line"); }'

   

A simple FileErrorHandler shows the base case.

FileErrorHandler errh1(stderr); f(&errh1); -| First line -| Second line -| here: warning: Third line

  

The simplest error veneer, PrefixErrorHandler, just prepends text to every line.

PrefixErrorHandler errh2(&errh1, "prefix - "); f(&errh2); -| prefix - First line -| prefix - Second line -| prefix - here: warning: Third line

   

ContextErrorHandler supplies a line of context before the first error message, and indents all messages except the context.

ContextErrorHandler errh3(&errh1, "This was called from ...", " "); f(&errh3); -| This was called from ... -| First line -| Second line -| here: warning: Third line

   

Note that the indentation is printed after the landmark. This often looks better than the alternative. Of course, an error veneer can take another error veneer as its "base handler", leading to cumulative effects. ContextErrorHandler errh4(&errh2, "This was called from ...", " "); f(&errh4); prefix - This was called from ... prefix - First line prefix - Second line prefix - here: ** warning: Third line

   

Writing ErrorHandlers

ErrorHandler constructs an error message using three virtual functions. The first, make_text, parses a format string and argument list into a single String. This is passed to the second function, decorate_text, which may transform the string. The final function, handle_text, prints the resulting error message. This structure makes ErrorHandler easy to extend. To write a new basic ErrorHandler, you will need to override just handle_text and the counting functions (nwarnings, nerrors, and reset_counts). The ErrorVeneer helper class, described below, lets you override just decorate_text when writing an error veneer.

virtual String make_text (Seriousness s, const char *format, va_list val) Method on ErrorHandler

Parses the format string format with arguments from val, returning the results as a String object.

The default implementation processes the formatting escapes described above (see Error Format Strings). It also prepends every line of the error message with warning: if s equals ERR_WARNING.

virtual String decorate_text (Seriousness s, const String &prefix, const String &landmark, const String &text) Method on ErrorHandler

Decorates the error message text as appropriate and returns the result. At minimum, every line of the result should be prepended by prefix and, if it is nonempty, the landmark string landmark.

The default implementation creates lines like this:

prefixlandmark: text (if landmark is nonempty) prefixtext (if landmark is empty)

        

Any spaces and/or a final colon are stripped from the end of landmark. Special landmarks, which begin and end with a backslash \, are ignored.

virtual void handle_text (Seriousness s, const String &text) Method on ErrorHandler

This method is responsible for printing or otherwise informing the user about the error message text. If s equals ERR_FATAL, the method should exit the program or perform some other drastic action. It should also maintain the nwarnings() and nerrors() counters. In most cases, it should ensure that the last character in text is a newline. This method has no default implementation.

The ErrorVeneer class, a subclass of ErrorHandler, supplies default implementations for these functions that ease the construction of new error veneers. ErrorVeneer's single instance variable, ErrorHandler *_errh, is the base handler. ErrorVeneer overrides all the relevant virtual functions--nwarnings, nerrors, reset_counts, make_text, decorate_text, and handle_text. Its versions simply delegate to the corresponding methods on _errh. An error veneer designer will generally subclass ErrorVeneer rather than ErrorHandler; then she will override only the methods she cares about (usually decorate_text), relying on ErrorVeneer's default implementations for the rest.

ErrorVeneer (ErrorHandler *base_errh) Constructor on ErrorVeneer

Constructs an ErrorVeneer helper class with base_errh as its base error handler. This constructor simply sets _errh = base_errh.

 
errorhandlers.txt · Last modified: 2007/02/22 10:00 by bart.braem
 
Recent changes RSS feed Driven by DokuWiki