From cd40d9e721eb4f5d05f57a74c6f1fd5d4aaef444 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Sun, 6 Dec 2015 17:28:39 +0100 Subject: [PATCH] Fixed #25657 -- Ignored exceptions when destroying geometry objects Due to randomness of garbage collection with geometry objects, it's easier to simply ignore AttributeError/TypeError generally raised when parts of objects are already garbage-collected. Thanks Sergey Fedoseev and Tim Graham for reviewing the patch. --- django/contrib/gis/gdal/datasource.py | 4 +++- django/contrib/gis/gdal/feature.py | 4 +++- django/contrib/gis/gdal/geometries.py | 4 +++- django/contrib/gis/gdal/raster/source.py | 4 +++- django/contrib/gis/gdal/srs.py | 8 ++++++-- django/contrib/gis/geos/geometry.py | 4 +++- django/contrib/gis/geos/prepared.py | 4 +++- django/contrib/gis/geos/prototypes/io.py | 4 +++- 8 files changed, 27 insertions(+), 9 deletions(-) diff --git a/django/contrib/gis/gdal/datasource.py b/django/contrib/gis/gdal/datasource.py index d73950f8604..74c1da342ed 100644 --- a/django/contrib/gis/gdal/datasource.py +++ b/django/contrib/gis/gdal/datasource.py @@ -87,8 +87,10 @@ class DataSource(GDALBase): def __del__(self): "Destroys this DataStructure object." - if self._ptr and capi: + try: capi.destroy_ds(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected def __iter__(self): "Allows for iteration over the layers in a data source." diff --git a/django/contrib/gis/gdal/feature.py b/django/contrib/gis/gdal/feature.py index 7e9d5a6986f..5c8c1a92331 100644 --- a/django/contrib/gis/gdal/feature.py +++ b/django/contrib/gis/gdal/feature.py @@ -29,8 +29,10 @@ class Feature(GDALBase): def __del__(self): "Releases a reference to this object." - if self._ptr and capi: + try: capi.destroy_feature(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected def __getitem__(self, index): """ diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index ac176670e96..64e9efb5bbf 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -121,8 +121,10 @@ class OGRGeometry(GDALBase): def __del__(self): "Deletes this Geometry." - if self._ptr and capi: + try: capi.destroy_geom(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected # Pickle routines def __getstate__(self): diff --git a/django/contrib/gis/gdal/raster/source.py b/django/contrib/gis/gdal/raster/source.py index 0f3a3a27443..904d2f783ad 100644 --- a/django/contrib/gis/gdal/raster/source.py +++ b/django/contrib/gis/gdal/raster/source.py @@ -131,8 +131,10 @@ class GDALRaster(GDALBase): raise GDALException('Invalid data source input type: "{}".'.format(type(ds_input))) def __del__(self): - if self._ptr and capi: + try: capi.close_ds(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected def __str__(self): return self.name diff --git a/django/contrib/gis/gdal/srs.py b/django/contrib/gis/gdal/srs.py index 8540fcaa152..ddb3ca061b6 100644 --- a/django/contrib/gis/gdal/srs.py +++ b/django/contrib/gis/gdal/srs.py @@ -96,8 +96,10 @@ class SpatialReference(GDALBase): def __del__(self): "Destroys this spatial reference." - if self._ptr and capi: + try: capi.release_srs(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected def __getitem__(self, target): """ @@ -341,8 +343,10 @@ class CoordTransform(GDALBase): def __del__(self): "Deletes this Coordinate Transformation object." - if self._ptr and capi: + try: capi.destroy_ct(self._ptr) + except (AttributeError, TypeError): + pass def __str__(self): return 'Transform from "%s" to "%s"' % (self._srs1_name, self._srs2_name) diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py index c0808f2e593..1aea19821dd 100644 --- a/django/contrib/gis/geos/geometry.py +++ b/django/contrib/gis/geos/geometry.py @@ -123,8 +123,10 @@ class GEOSGeometry(GEOSBase, ListMixin): Destroys this Geometry; in other words, frees the memory used by the GEOS C++ object. """ - if self._ptr and capi: + try: capi.destroy_geom(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected def __copy__(self): """ diff --git a/django/contrib/gis/geos/prepared.py b/django/contrib/gis/geos/prepared.py index ddabd011788..c18218bdf02 100644 --- a/django/contrib/gis/geos/prepared.py +++ b/django/contrib/gis/geos/prepared.py @@ -21,8 +21,10 @@ class PreparedGeometry(GEOSBase): self.ptr = capi.geos_prepare(geom.ptr) def __del__(self): - if self._ptr and capi: + try: capi.prepared_destroy(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected def contains(self, other): return capi.prepared_contains(self.ptr, other.ptr) diff --git a/django/contrib/gis/geos/prototypes/io.py b/django/contrib/gis/geos/prototypes/io.py index db64123e468..ed28bcdccdc 100644 --- a/django/contrib/gis/geos/prototypes/io.py +++ b/django/contrib/gis/geos/prototypes/io.py @@ -120,8 +120,10 @@ class IOBase(GEOSBase): def __del__(self): # Cleaning up with the appropriate destructor. - if self._ptr: + try: self._destructor(self._ptr) + except (AttributeError, TypeError): + pass # Some part might already have been garbage collected # ### Base WKB/WKT Reading and Writing objects ###