[postgis-users] Error handling: GEOS throws in PostGIS.
Martin Davis
mbdavis at VividSolutions.com
Fri Apr 11 17:10:26 PDT 2003
Is what you're suggesting this:
Catch all GEOS errors internally and return a status code instead. If a method already has a return value, return NULL
This seems like a pretty substantial change to GEOS. Does it mean that everyone using GEOS now has to check return codes, instead of using exceptions?
Is there any way of providing a yet higher wrapper in between GEOS and PostGIS which converts exceptions into return codes (so that GEOS is kept pure and PostGIS can call it safely)?
Martin Davis, Senior Technical Architect
Vivid Solutions Inc.
Suite #1A-2328 Government Street Victoria, B.C. V8T 5G5
Phone: (250) 385 6040 Fax: (250) 385 6046
EMail: mbdavis at vividsolutions.com Web: www.vividsolutions.com
> -----Original Message-----
> From: David Blasby [mailto:dblasby at refractions.net]
> Sent: Friday, April 11, 2003 3:26 PM
> To: postgis-users at postgis.refractions.net; GEOS Development List
> Subject: [postgis-users] Error handling: GEOS throws in PostGIS.
>
>
> I'm having troubles trapping exceptions thrown by GEOS in postgresql.
> My GEOS wrapper (postgis_geos_wrapper.cpp) looks like this:
>
>
> // call g1->contains(g2)
> // returns 0 = false
> // 1 = true
> // 2 = error was trapped
> char GEOSrelateContains(Geometry *g1, Geometry*g2)
> {
> try {
> bool result;
> result = g1->contains(g2);
> if (result)
> return 1;
> else
> return 0;
> }
> catch (...)
> {
> return 2;
> }
> }
>
> And in the .c PostGIS (postgis_geos.c):
>
> // overlaps(GEOMETRY g1,GEOMETRY g2)
> // returns if GEOS::g1->overlaps(g2) returns true
> // throws an error (elog(ERROR,...)) if GEOS throws an error
> PG_FUNCTION_INFO_V1(overlaps);
> Datum overlaps(PG_FUNCTION_ARGS)
> {
> GEOMETRY *geom1 = (GEOMETRY *)
> PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
> GEOMETRY *geom2 = (GEOMETRY *)
> PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
>
>
> Geometry *g1,*g2;
> bool result;
>
> errorIfGeometryCollection(geom1,geom2);
> initGEOS(MAXIMUM_ALIGNOF);
>
> g1 = POSTGIS2GEOS(geom1 );
> g2 = POSTGIS2GEOS(geom2 );
>
> GEOSdeleteGeometry(g1);
> GEOSdeleteGeometry(g2);
>
> result = GEOSrelateOverlaps(g1,g2);
> if (result == 2)
> {
> elog(ERROR,"GEOS overlaps() threw an error!");
> PG_RETURN_NULL(); //never get here
> }
>
> PG_RETURN_BOOL(result);
> }
>
>
> This works great in simple examples (like the test.c norman wrote).
> But, when you have another layer of indirection - like with
> postgresql,
> problems happen. I think the problem is with postgresql loading a
> C .so (postgis), which is linked to a C++ .so (GEOS). Postgresql
> is far removed from the GEOS error handling (in libc++).
>
> Basically, as soon as "g1->contains(g2);" throws an error that leaves
> the GEOS .so, postgresql dies immediately - the exception is not
> catch so terminate() is called.
>
> This doesnt happen if you are using GEOS in a c++ program, or using
> a C++ wrapper for a C program. It only has problems with 3 levels
> of indirection.
>
> Others have had this problem - for example people writing PERL modules
> that use the perl "C" api to call C++ libraries. People
> doing the same
> with PYTHON have also had problems. The only technical reference
> I can find is at:
> http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=37933
>
> Basically, there's a problem if libc is loaded before libc++.
>
> The only solution I can find to this (apart from forcing people to
> use a very up-to-date gcc/g++ and perhaps statically linking libc++ to
> postgresql) is actually write the C wrapper as part of GEOS.
>
> In order to test this, I modified GEOS so that GEOMETRY has a
> function:
>
> void Geometry::throw_exception()
> {
> throw "I see dead people!";
> }
>
>
> If you call g->throw_exception() in the postgis geos wrapper,
> postgresql
> will immediately die. But, if you re-write it (still in GEOS) like:
>
> void Geometry::throw_exception()
> {
> try
> {
> cout << "in throw_exception() try block - about to throw an
> error"<<endl;
> throw "I see dead people!";
> }
> catch (...)
> {
> cout << "in throw_exception() - caught an error"<<endl;
> return;
> }
> // never get here
> }
>
> You can successfully catch the error!
>
>
> So, unless anyone has any bright ideas, we could think about
> putting a C
> api directly in GEOS. If we use the standard C way of error handling
> (return an error code or NULL, like in the above), PostGIS
> should have
> no problems. Unfortunately, this does
> "pollute" GEOS.
>
> What think?
>
> dave
>
>
> _______________________________________________
> postgis-users mailing list
> postgis-users at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-users
>
More information about the postgis-users
mailing list