[GRASS-dev] GRASS & QGIS: the future

Glynn Clements glynn at gclements.plus.com
Sat Apr 19 15:03:09 PDT 2014


Vaclav Petras wrote:

> > > Unfortunately GRASS 7 moved ahead towards its aim "to make life harder
> > > for anyone trying to use the GRASS libraries" [1].
> >
> > That isn't actually the reason why various functions have had status
> > returns changed to fatal errors. The reason is to avoid pushing the
> > burden of error handling onto their callers.
> 
> The fact is that no library should use exit() or similar things if it wants
> to be general. GRASS library is intended to be used only for building GRASS
> modules, thus it is specialized for them, thus it uses G_fatal_error() with
> exit(). (At least there is a believe that exit makes it easier.)

It's not exit() per se, but the __attribute__((noreturn)) semantics
which makes things easier. IOW, calling G_fatal_error() ensures that
the remainder of the function will not be executed, and control will
not be returned to the caller.

Calling abort() or longjmp() or or anything else which doesn't return
would work equally well.

Essentially, G_fatal_error() generates an "exception", something which
escapes from the normal flow of control.

It's sometimes referred to as the "Samurai Principle": return
victorious, or don't return at all.

Note that libpng uses the same idiom. By default, errors result in a
longjmp(); the caller must use setjmp() to register an error handler. 
If you compile with PNG_NO_SETJMP (or don't use setjmp), it uses
PNG_ABORT(), which calls abort(). This can be overridden, subject to a
constraint which should be familiar by now:

       You can #define PNG_ABORT() to a function that does something
       more useful than abort(), as long as your function does not
       return.

> As a result using GRASS functions outside the scope of GRASS modules
> requires another library. It would be nice to have two libraries, one for
> GRASS modules (with exit()) and one for everybody else. Hopefully, it would
> be possible to share the same code to some extent. Alternative is to use
> the RPC wrapper as suggested earlier by Soeren, as far as I understand this
> has the same result. The questions are what is less work, less duplication,
> what has easier maintenance and what is easier to do for all the platforms.

An RPC wrapper would move the execution of GRASS functions into a new
process (i.e. a server). If the call generates a fatal error, the
server dies, the client detects this and reports an error rather than
a result.

The main problem with this is that any error loses the entire state
held on the server, e.g. any open maps no longer exist.

Using setjmp/longjmp would be more useful, but it would require some
effort to add clean-up code to functions so that core data structures
aren't left in an inconsistent state.

E.g. rather than sequentially overwriting the fields of a structure
with values obtained from functions which can generate a fatal error,
you first obtain the values and store them in variables, then fill in
the structure last, so that a failure doesn't result in a structure
which is only partially updated.

-- 
Glynn Clements <glynn at gclements.plus.com>


More information about the grass-dev mailing list