Provided by: elektra-doc_0.8.14-5_all bug

NAME

       md_doc_help_elektra-error-handling - elektra-error-handling(7) -- error handling in
       Elektra You might want to read about data structures first.

       It is sometimes unavoidable that errors occur that ultimately have an impact for the user.
       Examples for such an error are that hard disc space is exhausted. For a library it is
       necessary to pass information about the facts and circumstances to the user because the
       user wants to be informed why a requested action failed. So Elektra gathers all
       information in these situations. We call this resulting information error information and
       warning information depending on the severity.

       If the occurred error is critical and ultimately causes a situation that the post
       conditions cannot be fulfilled we say that Elektra comes into a faulty state. Such a
       faulty state will change the control flow inside Elektra completely. Elektra is unable to
       resolve the problem without assistance. After cleaning up resources, a faulty state leads
       to immediate return from the function with an error code. As a user expects from a
       library, Elektra never calls exit() or something similar, regardless of how fatal the
       error is. In this situation error information should be set.

       On the other hand, for many problems the work can go on with reasonable defaults.
       Nevertheless, the user will be warned that a problem occurred using the warning
       information. These situations do not influence the control flow. But applications can
       choose to react differently in the presence of warning information. They may not be
       interested in any warning information at all. It is no problem if warning information is
       ignored because they are stored and remain accessible in a circular buffer. The
       implementation prevents an overflow of the buffer. Instead the oldest warnings are
       overwritten.

       When error or warning information is presented to the user, it is called error message or
       warning message. The user may reply to this message in which way to continue.

   Error vs. Warning Information
       When an error in an faulty state occurs, the error information must still hold the
       original error information. So even in problems that would cause a faulty state,
       otherwise, the error information must be omitted or transformed to a warning information.
       In some places only the adding of warning information is possible:

       • The main purpose of kdbClose() is to free the handle. This operation is always
         successful and is carried out even if some of the resources cannot be freed. Therefore,
         in kdbClose(), setting error information is prohibited. Warning information is, however,
         very useful to tell the user the circumstance that some actions during cleanup failed.

        Also in kdbOpen(), only adding warning information is allowed. If kdbOpen() is not able
         to open a plugin, the affected backend will be dropped out. The user is certainly
         interested why that happened. But it was decided not to make it an faulty state, because
         the application might not even access the faulty part of the key hierarchy. An exception
         to this rule is if kdbOpen() fails to open the default backend. This situation will
         induce an faulty state.

        In kdbSet(), the cleaning up of resources involves calling plugins. But during this
         process Elektra is in a faulty state, so only adding of warning information is allowed.
         This ensures that the original error information is passed unchanged to the user.

       On the other hand, any access to the key database can produce warning information. Plugins
       are allowed to yield warning information at any place and for any reason. For example, the
       storage plugin reading a configuration file with an old syntax, is free to report the
       circumstance as warning information. Warning information is also useful when more than one
       fact needs to be reported.

   Error Information
   Reporting Errors
       Reporting errors is a critical task. Users expect different aspects:

       • The {user of the application} does not want to see any error message at all. If it is
         inevitable, he or she wants little, but very concrete information, about what he or she
         needs to do. The message should be short and concise. Some error information may already
         be captured by the application, but others like ''no more free disk space'' have to be
         displayed. Conflicts should also be presented to the user. It is a good idea to ask how
         to proceed if a diversity of possible reactions exists. In case of conflicts, the user
         may have additional knowledge about the other program which has caused the problem. The
         user is more likely to decide correctly by which strategy the configuration shall be
         restored.

       • The {user of the library} wants more detailed information. Categories of how severe the
         error is can help to decide how to proceed. Even more important is the information if it
         makes sense to try the same action again. If, for example, an unreliable network
         connection or file system is used, the same action can work in a second try.

       • A {developer of the library}{Library refers to both Elektra's core and plugins.} wants
         full information about anything needed to be able to reproduce and locate potential
         bugs. Ideally the error information should even mention the file and line where the
         error occurred. This can help developers to decide if there is a bug inside Elektra or
         if the problem lies somewhere else.

       • Vast information is needed to support correct error handling in [programming
         language]{other programming languages}. In languages supporting exceptions, class name,
         inheritance or interface information may be necessary. Language specific extensions are,
         however, not limited to exceptions. Other ways of handling errors are continuations or
         longjmp in C. A plugin is free to add, for example, jmp_buf information to the error
         information.

       It is certainly not a good idea to put all this previously mentioned information into a
       single string. Elektra chooses another way described in the next chapter.

   Metadata
       As stated above, a library always informs the user about what has happened, but does not
       print or log anything itself. One way to return an error information is to add a parameter
       containing the error information. In the case of Elektra, all KDB methods have a key as
       parameter. This key is additionally passed to every plugin. The idea is to add the error
       and warning information as metadata to this key. This approach does not limit flexibility,
       because a key can hold a potentially unlimited number of metakeys.

       The error information is categorised in metadata as follows:

       • [error] indicates that an faulty state is present. The value of the metakey contains the
         name of all the subkeys that are used for error indication. Metakeys do not guarantee
         any particular order on iteration. Instead the user can find out the information by
         looking at this metavalue.

       Additional metakeys yield all the details.

       • [error/number] yields a unique number for every error.

       • [error/description] is a description for the error to be displayed to the user. For
         example, the metavalue can hold the text ''could not write to file''.

       • [error/reason] specifies the reason of the error. The human readable message is in the
         metavalue of error/reason. It states why the error occurred. One example for it is ''no
         disc space available''.

       • [error/ingroup] contains ''kdb'' if the error occurred inside the core. It contains
         ''module'' if the error happened while loading a module. The metavalue is ''plugin'' if
         the error information comes from a plugin.

       • [error/module] indicates the name of the specific module or plugin.

       • [error/file] yields the source file from where the error information comes.

       • [error/line] represents the exact line of that source file.

       As we see, the system is powerful because any other text or information can be added in a
       flexible manner by using additional metakeys.

   Error Specification
       The error specification in Elektra is written in simple colon-separated text files. Each
       entry has a unique identifier and all the information we already discussed above. No part
       of Elektra ever reads this file directly. Instead it is used to generate source code which
       contains everything needed to add a particular error or warning information. With that
       file we achieved a central place for error-related information. All other locations are
       automatically generated instead of having error-prone duplicated code. This principle is
       called ''Don't repeat yourself''.

       In Elektra's core and plugins, C macros are responsible for setting the error information
       and adding warning information. In C only a macro is able to add the file name and line
       number of the source code. In language bindings other code may be generated.

   Sources of Errors
       Key and KeySet functions cannot expose more error information than the error code they
       return. But, of course, errors are also possible in these functions. Typically, errors
       concern invalid key names or null pointers. These problems are mostly programming errors
       with only local effects.

       The most interesting error situations, however, all occur in KDB. The error system
       described here is dedicated to the four main KDB functions: kdbOpen(), kdbGet(), kdbSet()
       and kdbClose(). The place where the configuration is checked and made persistent is the
       source of most error information. At this specific place a large variety of errors can
       happen ranging from opening, locking up and saving the file. Sometimes in plugins, nearly
       every line needs to deal with an error situation.

   Exceptions
       Exceptions are a mechanism of the language and not just an implementation detail.
       Exceptions are not intended to force the user to do something, but to enrich the
       possibilities. In this section, we discuss two issues related to exceptions. On the one
       hand, we will see how Elektra supports programming languages that provide exceptions. On
       the other hand, we will see how the research in exceptions helps Elektra to provide more
       robustness.

   Language Bindings
       C does not know anything about exceptions. But Elektra was designed so that both plugins
       and applications can be written in languages that provide exceptions. One design goal of
       Elektra's error system is to transport exception-related information in a language neutral
       way from the plugins to the applications. To do so, a language binding of the plugin needs
       to catch every exception and transform it into error information and return an error code.

       Elektra recognises the error code, stops the processing of plugins, switches to a faulty
       state and gives all the plugins a chance to do the necessary cleanups. The error
       information is passed to the application as usual. If the application is written in C or
       does not want to deal with exceptions for another reason, we are finished because the
       application gets the error information inside metadata as expected. But, if the
       application is written in another language, the binding translates the error code to an
       exception and throws it. It is worth noting that the source and target language do not
       need to be the same.

       Such a system needs a central specification of error information. We already introduced
       such a specification file in error specification. The exception classes and converters can
       be generated from it. An exception converter is either a long sequence of try-catch
       statements that transforms every known exception into an appropriate metakeys. Each
       exception thrown by the plugin has to be caught. Alternatively, a converter can be a long
       switch statement for every error number. In every case the appropriate exception is
       thrown.

       The motivation for using exceptions is that in C every return value has to be checked. On
       the other hand, the C++ exception mechanism allows the programmer to throw an exception in
       any place and catch it where it is needed. So in C++ the code is not cluttered with parts
       responsible for error handling. Instead, in a single place all exceptions of a plugin can
       be transformed to Elektra's error or warning information. The code for this place can be
       generated automatically using an exception converter.

       Applications not written in C can also benefit from an exception converter. Instead of
       using the metadata mechanism, the error information can be converted to the exception
       mechanism already used for that application. We see that Elektra is minimally invasive in
       this regard.

   Exception Safety
       We can learn from the way languages define the semantics for exception safety. Exception
       safety is a concept which ensures that all resources are freed regardless of the chosen
       return path. Basic guarantees make sure that some invariants remain on an object even in
       exceptional cases. On the other hand, strong guarantees assure that the investigated
       operation is successful or has no effect at all. Methods are said to be exception safe if
       the object remains in a valid state. The idea of exception safety is to ensure that no
       resource leaking is possible. kdbSet() written in C++ would look like:

           try {
                   plugin[1].set(); // may throw plugin[2].set(); // may
                   throw plugin[3].set(); // may throw ...

                   plugin[PLUGIN_COMMIT].set(); // now all changes are
                   committed
           } catch (...) {
                   // error situation, roll back the changes
                   plugin[1].error(); // does not throw plugin[2].error();
                   // does not throw plugin[3].error(); // does not throw ...

                   // now all changes are rolled back return -1;
           } // now do all actions on success after commit
           plugin[POSTCOMMIT].set(); // does not throw ...  return 1; //
           commit successful

       This pseudo code is much clearer than the corresponding C code. Let us explain the
       guarantee Elektra provides using this example. One by one plugin gets its chance to
       process the configuration. If any plugin fails, the semantics resemble that of a thrown
       exception. All other plugins will not be executed. Instead, the plugins get a chance to
       recover from the faulty state. In this catch part, the plugins are not allowed to yield
       any error information, but they are allowed to add warnings.

       Continue reading with the algorithm.

Version 0.8.14                           Tue Dec 15 2md5doc_help_elektra-error-handling(3elektra)