[GRASS-dev] Vect_*_fatal_error()

Glynn Clements glynn at gclements.plus.com
Sat Nov 12 06:46:51 EST 2011


Martin Landa wrote:

> it continues with all wxGUI components which are using GRASS
libraries via ctypes.

The number of such components should be zero.

> Just try to use vector digitizer
> or wxNViz, the whole GUI just crashes without any kind of message when
> G_fatal_error() is called.

Yep. The solution has been made clear on multiple occasions: don't
access GRASS libraries from the main GUI process. wxNVIZ in particular
should absolutely be a separate process (OpenGL drivers are not noted
for their stability).

Even if the exit()-on-fatal-error issue magically disappeared, the
memory management issues (i.e. don't bother tracking allocations which
don't matter for a typical module) won't. Nor will the fact that
"try ... except" won't catch a segfault.

grass.lib.* exists for "module-style" scripts, not for persistent
applications.

> Well due to design, anyway very user
> friendly. I am not a fan of G_set_fatal_error() solution, on the other
> hand I don't see any reason why to *forbid* so strictly the
> programmers which are using GRASS libraries to avoid calling system
> exit on G_fatal_error(). The default behaviour will remain! We just
> let other programmers (with a big warning) to use GRASS libraries for
> the purpose which they were not originally designed nothing more.

Allowing G_fatal_error() to return isn't going to stop wxGUI, QGIS,
etc terminating unexpectedly. It's just going to make them terminate
via a segfault rather than via exit().

If a function calls G_fatal_error(), it isn't expecting it to return. 
If it does return, the usual result will be that the caller attempts
to use invalid data; a crash isn't likely to be far off.

A typical example of G_fatal_error() usage is:

	FILE *fp = fopen(...);
	if (!fp)
	    G_fatal_error(...);
	fread(..., fp);

Allowing G_fatal_error() to return will simply replace the exit() with
a segfault. Why would this be an improvement?

If you want to (attempt to) recover from fatal errors, you have to
escape from G_fatal_error() via a longjmp(). Either that, or you have
to re-write every single use of G_fatal_error() (~3800 of them) to
accomodate the possibility of it returning.

Except that the latter isn't really an acceptable solution, as it
pushes the burden of error handling on to everything else. You might
consider making your job easier justifies making everyone else's
harder, but don't expect everyone else to agree.

So long as I have commit privileges, G_fatal_error() is going to
retain (and honour) the "noreturn" attribute.

Aside: In 7.0, I changed a number of library functions which had
previously returned a status code to call G_fatal_error() instead. 
This meant eliminating the status-checking from the callers, as the
return type changed from "int" to "void".

Which lead me to discover that, for modules, actually bothering to
check the status code tended to be the exception rather than the rule. 
IOW, even with most functions using G_fatal_error() to eliminate the
need to check status codes, the burden of dealing with the few which
didn't was still too much.

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


More information about the grass-dev mailing list