[geos-devel] Re: [postgis-users] Error handling: GEOS throws in PostGIS.

Paul Ramsey pramsey at refractions.net
Fri Apr 11 20:16:31 EDT 2003


Dave is suggesting your second option, adding a wrapper (perhaps as part 
of GEOS) which provides access to the GEOS functionality, but with all 
the exceptions kept hidden from the outside world.

It is not pretty, but we appear to have no other option.

P.

Martin Davis wrote:
> 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
>> 
> 
> 
> _______________________________________________ postgis-users mailing
> list postgis-users at postgis.refractions.net 
> http://postgis.refractions.net/mailman/listinfo/postgis-users


-- 
       __
      /
      | Paul Ramsey
      | Refractions Research
      | Email: pramsey at refractions.net
      | Phone: (250) 885-0632
      \_




More information about the geos-devel mailing list