[GRASS-dev] [Qgis-developer] GRASS & QGIS: the future

Glynn Clements glynn at gclements.plus.com
Thu Apr 24 20:49:11 PDT 2014


Sören Gebbert wrote:

> > Vector lib does not call G_fatal_error(), it was written in parallel
> > with QGIS plugin with vector editing in mind. I hope it is still true.
> 
> I fear that might be not the case anymore. For example, all memory
> allocation functions G_calloc(), G_malloc() and G_realloc() will call
> G_fatal_error() in case the memory allocation fails. As far as i can
> tell the vector library make often use of this functions. So we have
> the problem that basic core functions call G_fatal_error() that are
> used all over the place in GRASS GIS.

Memory allocation is largely a theoretical problem. If you're out of
memory, there's no guarantee that whatever error-handling mechanism
you come up with can function (e.g. printing an error message may
result in a malloc() within libc's stdio functions).

> If you patch GRASS to use setjmp/longjmp to implement an exception
> like behavior then you need to write clean up code for static
> variables and dynamically allocated memory. A G_fatal_error() call can
> be deeply nested in a library function. Cleaning only the static
> variables to be in usable state will lead to problematic memory leaks.
> So it is a complex task in GRASS.

Memory leaks are another area where GRASS libraries aren't
particularly suitable for persistent applications.

In general, any leak which has no significance for a command-line
module is considered not significant, period.

Many strings inside the library are dynamically allocated and never
freed (rather, they're implicitly freed upon process termination). 
This means that the library can just return a pointer and nothing
needs to worry about that pointer becoming invalid (because it will
remain valid for the lifetime of the process).

Allowing such data to be freed would require either keeping track of
usage (e.g. reference counting) or duplicating the underlying data
rather than simply returning a pointer to it.

> Using setjmp/longjmp in QGIS wrapping all GRASS functions that might
> call G_fatal_error() is complex, since a G_fatal_error() call can be
> deeply nested in a library function. You need to keep track of this
> resulting in plenty setjmp wrappers around GRASS functions.
> You need to cleanup global static structures as well and you will have
> no control over pointers pointing to dynamic allocated memory that got
> lost in a longjmp.

If it can be gotten to the point where memory leaks are the only
problem, there isn't really that much of a problem, given that we're
talking about the behaviour in "exceptional" conditions.

The more fundamental problem is e.g. allocating a "slot" from an
array, starting to fill in its fields, and aborting (longjmp,
exception, etc) part-way through. Or doing something similar with
groups of related variables.

Anything which iterates over the array is going to encounter a slot
where some of the fields contain garbage. If those fields are
pointers, offsets, lengths, etc, the likely result is a segfault.

> Having a kind of garbage collector in GRASS, implemented in the
> G_*alloc() functions, may solve many problems. But i have no idea
> howto implement the garbage collector to detect pointers that got
> orphaned in a longjmp to automagically clean them.

I don't think that's realistic.

There are simpler things which would help in many cases; e.g. in the
"slots" case, not allocating the slot until after you've obtained all
of the values which are needed to initialise it.

Beyond that, we have to deal with C's lack of destructors. We may want
to maintain a stack of cleanup handlers (i.e. destructors) which would
be executed in the event of a fatal error. Code which needs to ensure
some form of cleanup occurs would push handlers as resources are
allocated, and pop them prior to a normal return.

This would avoid having to implement nested try/catch constructs using
setjmp/longjmp and G_set_error_routine. In fact, that currently isn't
possible, as you can't get at the existing fatal error handler in
order to save and restore it around an local handler.

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


More information about the grass-dev mailing list