[geos-devel] RE: Error handling: GEOS throws in PostGIS.

Martin Davis mbdavis at VividSolutions.com
Fri Apr 11 20:11:10 EDT 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
> 

_______________________________________________
postgis-users mailing list
postgis-users at postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users



More information about the geos-devel mailing list