grub2-dev: Error Handling
1
1 6 Error Handling
1 ****************
1
1 Error handling in GRUB 2 is based on exception handling model. As C
1 language doesn't directly support exceptions, exception handling
1 behavior is emulated in software.
1
1 When exception is raised, function must return to calling function.
1 If calling function does not provide handling of the exception it must
1 return back to its calling function and so on, until exception is
1 handled. If exception is not handled before prompt is displayed, error
1 message will be shown to user.
1
1 Exception information is stored on 'grub_errno' global variable. If
1 'grub_errno' variable contains value 'GRUB_ERR_NONE', there is no active
1 exception and application can continue normal processing. When
1 'grub_errno' has other value, it is required that application code
1 either handles this error or returns instantly to caller. If function
1 is with return type 'grub_err_t' is about to return 'GRUB_ERR_NONE', it
1 should not set 'grub_errno' to that value. Only set 'grub_errno' in
1 cases where there is error situation.
1
1 Simple exception forwarder.
1 grub_err_t
1 forwarding_example (void)
1 {
1 /* Call function that might cause exception. */
1 foobar ();
1
1 /* No special exception handler, just forward possible exceptions. */
1 if (grub_errno != GRUB_ERR_NONE)
1 {
1 return grub_errno;
1 }
1
1 /* All is OK, do more processing. */
1
1 /* Return OK signal, to caller. */
1 return GRUB_ERR_NONE;
1 }
1
1 Error reporting has two components, the actual error code (of type
1 'grub_err_t') and textual message that will be displayed to user. List
1 of valid error codes is listed in header file 'include/grub/err.h'.
1 Textual error message can contain any textual data. At time of writing,
1 error message can contain up to 256 characters (including terminating
1 NUL). To ease error reporting there is a helper function 'grub_error'
1 that allows easier formatting of error messages and should be used
1 instead of writing directly to global variables.
1
1 Example of error reporting.
1 grub_err_t
1 failing_example ()
1 {
1 return grub_error (GRUB_ERR_FILE_NOT_FOUND,
1 "Failed to read %s, tried %d times.",
1 "test.txt",
1 10);
1 }
1
1 If there is a special reason that error code does not need to be
1 taken account, 'grub_errno' can be zeroed back to 'GRUB_ERR_NONE'. In
1 cases like this all previous error codes should have been handled
1 correctly. This makes sure that there are no unhandled exceptions.
1
1 Example of zeroing 'grub_errno'.
1 grub_err_t
1 probe_example ()
1 {
1 /* Try to probe device type 1. */
1 probe_for_device ();
1 if (grub_errno == GRUB_ERR_NONE)
1 {
1 /* Device type 1 was found on system. */
1 register_device ();
1 return GRUB_ERR_NONE;
1 }
1 /* Zero out error code. */
1 grub_errno = GRUB_ERR_NONE;
1
1 /* No device type 1 found, try to probe device type 2. */
1 probe_for_device2 ();
1 if (grub_errno == GRUB_ERR_NONE)
1 {
1 /* Device type 2 was found on system. */
1 register_device2 ();
1 return GRUB_ERR_NONE;
1 }
1 /* Zero out error code. */
1 grub_errno = GRUB_ERR_NONE;
1
1 /* Return custom error message. */
1 return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No device type 1 or 2 found.");
1 }
1
1 Some times there is a need to continue processing even if there is a
1 error state in application. In situations like this, there is a needed
1 to save old error state and then call other functions that might fail.
1 To aid in this, there is a error stack implemented. Error state can be
1 pushed to error stack by calling function 'grub_error_push ()'. When
1 processing has been completed, 'grub_error_pop ()' can be used to pop
1 error state from stack. Error stack contains predefined amount of error
1 stack items. Error stack is protected for overflow and marks these
1 situations so overflow error does not get unseen. If there is no space
1 available to store error message, it is simply discarded and overflow
1 will be marked as happened. When overflow happens, it most likely will
1 corrupt error stack consistency as for pushed error there is no matching
1 pop, but overflow message will be shown to inform user about the
1 situation. Overflow message will be shown at time when prompt is about
1 to be drawn.
1
1 Example usage of error stack.
1 /* Save possible old error message. */
1 grub_error_push ();
1
1 /* Do your stuff here. */
1 call_possibly_failing_function ();
1
1 if (grub_errno != GRUB_ERR_NONE)
1 {
1 /* Inform rest of the code that there is error (grub_errno
1 is set). There is no pop here as we want both error states
1 to be displayed. */
1 return;
1 }
1
1 /* Restore old error state by popping previous item from stack. */
1 grub_error_pop ();
1