[GRASS-dev] set_fatal_error

Martin Landa landa.martin at gmail.com
Fri Jan 18 17:38:22 EST 2008


Hi,

2008/1/16, Glynn Clements <glynn at gclements.plus.com>:

> > > > We already have G_set_error_routine(). However, a fundamental property
> > > > of G_fatal_error() is that it doesn't return (that's why the "fatal"
> > > > is part of the name).
> > >
> > > right, but it doesn't avoid calling exit(EXIT_FAILURE) in G_fatal_error().
> > >
> > > Calling G_fatal_error() causes crashing wxPython GUI e.g. during
> > > digitization. I am not sure how to handle this, since G_fatal_error()
> > > is widely used in Vector library. I guess this could be possible to
> > > solve by using separate thread in Python code(?).
> > >
> > > The second point, I guess it was the reason (crashing e.g. qgis) why
> > > (probably by Radim) Vect_*_fatal_error() were added to Vect library.
> > > But it is used only in open.c and legal_vname.c as far as i know.
> > >
> > > Avoiding calling exit() in G_fatal_error() in the given case would
> > > make sense, maybe.
> >
> > I meant something like:
> >
> > int G_fatal_error (const char *msg,...)
> > {
> >     char buffer[2000];  /* No novels to the error logs, OK? */
> >     va_list ap;
> >
> >     va_start(ap,msg);
> >     vsprintf(buffer,msg,ap);
> >     va_end(ap);
> >
> >     print_error (buffer,ERR);
> >
> >     if (ferror == G_FATAL_RETURN) {
> >       return EXIT_FAILURE;
> >     }
>
> Nope; G_fatal_error() must *never* return; that's the whole point.
>
> >     exit (EXIT_FAILURE);
>
> Code which calls G_fatal_error() relies upon it not returning. If it
> were to return, the caller would most likely just crash as a
> consequence of whichever "error" it was using G_fatal_error() to
> report.
>
> E.g. if you have the following code:
>
>         struct foo *p = get_foo();
>         if (!p)
>                 G_fatal_error("...");
>         if (p->foo)
>                 ...;
>
> If G_fatal_error() returns, you will just get a segfault when the code
> dereferences the pointer.
>
> Code which calls G_fatal_error() isn't just expecting an error message
> to be printed. More importantly, it expects execution of the remainder
> of the function to be aborted.
>
> Many GRASS functions are written (and used) on the assumption that
> they cannot fail. They either succeed, or they never return (because
> any errors result in a call to G_fatal_error(), which never returns).
>
> The GRASS libraries were designed for use in one-shot utilities.
> Making them useful for persistent applications is going to require a
> substantial re-write. You can't just tweak G_fatal_error(); you have
> to re-write everything which calls it to actually recover from errors
> rather than just terminating the program as soon as anything goes
> wrong.
>
> Even if you take the approach QGIS uses and install an error handler
> which longjmp()s out to the caller, you have to allow for the fact
> that the data structures used by the GRASS libraries may be left in an
> inconsistent state, so subsequent library calls may simply segfault.

well, thanks a lot for the clarification.

Regards, Martin

-- 
Martin Landa <landa.martin at gmail.com> * http://gama.fsv.cvut.cz/~landa *


More information about the grass-dev mailing list