Skip to content

Commit 2f83949

Browse files
committed
fix: Improve Signer cleanup
1 parent 732d456 commit 2f83949

File tree

1 file changed

+41
-17
lines changed

1 file changed

+41
-17
lines changed

src/c2pa/c2pa.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,8 +1102,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
11021102
self.close()
11031103

11041104
def __del__(self):
1105-
"""Ensure resources are cleaned up if close()
1106-
wasn't called.
1105+
"""Ensure resources are cleaned up if close()wasn't called.
11071106
11081107
This destructor only cleans up if the object
11091108
hasn't been explicitly closed.
@@ -1217,9 +1216,7 @@ class Reader:
12171216
@classmethod
12181217
def get_supported_mime_types(cls) -> list[str]:
12191218
"""Get the list of supported MIME types for the Reader.
1220-
1221-
This method retrieves supported MIME types from the native library
1222-
with proper pointer validation and error handling.
1219+
This method retrieves supported MIME types from the native library.
12231220
12241221
Returns:
12251222
List of supported MIME type strings
@@ -1808,6 +1805,41 @@ def __exit__(self, exc_type, exc_val, exc_tb):
18081805
"""Context manager exit."""
18091806
self.close()
18101807

1808+
def _cleanup_resources(self):
1809+
"""Internal cleanup method that safely releases native resources.
1810+
1811+
This method handles the actual cleanup logic and can be called
1812+
from both close() and __del__ without causing double frees.
1813+
"""
1814+
try:
1815+
# Only cleanup if not already closed and we have a valid signer
1816+
if hasattr(self, '_closed') and not self._closed:
1817+
if hasattr(self, '_signer') and self._signer:
1818+
try:
1819+
_lib.c2pa_signer_free(self._signer)
1820+
except Exception:
1821+
# Cleanup failure doesn't raise exceptions
1822+
pass
1823+
finally:
1824+
self._signer = None
1825+
1826+
# Clear callback reference to prevent cycles
1827+
if hasattr(self, '_callback_cb'):
1828+
self._callback_cb = None
1829+
1830+
self._closed = True
1831+
except Exception:
1832+
# Ensure we don't raise exceptions during cleanup
1833+
pass
1834+
1835+
def __del__(self):
1836+
"""Ensure resources are cleaned up if close() wasn't called.
1837+
1838+
This destructor safely handles cleanup without causing double frees.
1839+
It only cleans up if the object hasn't been explicitly closed.
1840+
"""
1841+
self._cleanup_resources()
1842+
18111843
def close(self):
18121844
"""Release the signer resources.
18131845
@@ -1820,16 +1852,10 @@ def close(self):
18201852
return
18211853

18221854
try:
1823-
if self._signer:
1824-
try:
1825-
_lib.c2pa_signer_free(self._signer)
1826-
except Exception as e:
1827-
print(
1828-
Signer._ERROR_MESSAGES['signer_cleanup'].format(
1829-
str(e)), file=sys.stderr)
1830-
finally:
1831-
self._signer = None
1855+
# Use the internal cleanup method
1856+
self._cleanup_resources()
18321857
except Exception as e:
1858+
# Log any unexpected errors during close
18331859
print(
18341860
Signer._ERROR_MESSAGES['cleanup_error'].format(
18351861
str(e)), file=sys.stderr)
@@ -1893,9 +1919,7 @@ class Builder:
18931919
@classmethod
18941920
def get_supported_mime_types(cls) -> list[str]:
18951921
"""Get the list of supported MIME types for the Builder.
1896-
1897-
This method retrieves supported MIME types from the native library
1898-
with proper pointer validation and error handling.
1922+
This method retrieves supported MIME types from the native library.
18991923
19001924
Returns:
19011925
List of supported MIME type strings

0 commit comments

Comments
 (0)