@@ -1679,7 +1679,17 @@ def __init__(self, signer_ptr: ctypes.POINTER(C2paSigner)):
16791679
16801680 Note: This constructor is not meant to be called directly.
16811681 Use from_info() or from_callback() instead.
1682+
1683+ Args:
1684+ signer_ptr: Pointer to the native C2PA signer
1685+
1686+ Raises:
1687+ C2paError: If the signer pointer is invalid
16821688 """
1689+ # Validate pointer before assignment
1690+ if not signer_ptr :
1691+ raise C2paError ("Invalid signer pointer: pointer is null" )
1692+
16831693 self ._signer = signer_ptr
16841694 self ._closed = False
16851695
@@ -1854,40 +1864,85 @@ def wrapped_callback(
18541864
18551865 def __enter__ (self ):
18561866 """Context manager entry."""
1857- if self ._closed :
1858- raise C2paError (Signer ._ERROR_MESSAGES ['closed_error' ])
1867+ self ._ensure_valid_state ()
1868+
1869+ # Additional pointer validation before entering context
1870+ if not self ._signer :
1871+ raise C2paError ("Invalid signer pointer: pointer is null" )
1872+
18591873 return self
18601874
18611875 def __exit__ (self , exc_type , exc_val , exc_tb ):
18621876 """Context manager exit."""
18631877 self .close ()
18641878
1879+ def _cleanup_resources (self ):
1880+ """Internal cleanup method that safely releases native resources.
1881+
1882+ This method handles the actual cleanup logic and can be called
1883+ from both close() and __del__ without causing double frees.
1884+ """
1885+ try :
1886+ if not self ._closed and self ._signer :
1887+ try :
1888+ _lib .c2pa_signer_free (self ._signer )
1889+ except Exception :
1890+ # Log cleanup errors but don't raise exceptions
1891+ logger .warning ("Failed to free native Signer resources" )
1892+ finally :
1893+ self ._signer = None
1894+
1895+ # Clean up callback reference
1896+ if self ._callback_cb :
1897+ self ._callback_cb = None
1898+
1899+ self ._closed = True
1900+ except Exception :
1901+ # Ensure we don't raise exceptions during cleanup
1902+ pass
1903+
1904+ def _ensure_valid_state (self ):
1905+ """Ensure the signer is in a valid state for operations.
1906+
1907+ Raises:
1908+ C2paError: If the signer is closed or invalid
1909+ """
1910+ if self ._closed :
1911+ raise C2paError (Signer ._ERROR_MESSAGES ['closed_error' ])
1912+ if not self ._signer :
1913+ raise C2paError (Signer ._ERROR_MESSAGES ['closed_error' ])
1914+
18651915 def close (self ):
1866- """Release the signer resources.
1916+ """Release the signer resources safely .
18671917
18681918 This method ensures all resources are properly cleaned up,
18691919 even if errors occur during cleanup.
1870- Errors during cleanup are logged but not raised to ensure cleanup.
1871- Multiple calls to close() are handled gracefully.
1920+
1921+ Note:
1922+ Multiple calls to close() are handled gracefully.
1923+ Errors during cleanup are logged but not raised
1924+ to ensure cleanup.
18721925 """
18731926 if self ._closed :
18741927 return
18751928
18761929 try :
1877- if self . _signer :
1878- try :
1879- _lib . c2pa_signer_free ( self . _signer )
1880- except Exception as e :
1881- logger . error (
1882- Signer . _ERROR_MESSAGES [ 'signer_cleanup' ]. format (
1883- str ( e )))
1884- finally :
1885- self . _signer = None
1930+ # Validate pointer before cleanup if it exists
1931+ if self . _signer and self . _signer != 0 :
1932+ # Use the internal cleanup method
1933+ self . _cleanup_resources ()
1934+ else :
1935+ # Make sure to release the callback
1936+ if self . _callback_cb :
1937+ self . _callback_cb = None
1938+
18861939 except Exception as e :
1940+ # Log any unexpected errors during close
18871941 logger .error (
18881942 Signer ._ERROR_MESSAGES ['cleanup_error' ].format (
18891943 str (e )))
18901944 finally :
1945+ # Always mark as closed, regardless of cleanup success
18911946 self ._closed = True
18921947
18931948 def reserve_size (self ) -> int :
@@ -1899,8 +1954,7 @@ def reserve_size(self) -> int:
18991954 Raises:
19001955 C2paError: If there was an error getting the size
19011956 """
1902- if self ._closed or not self ._signer :
1903- raise C2paError (Signer ._ERROR_MESSAGES ['closed_error' ])
1957+ self ._ensure_valid_state ()
19041958
19051959 result = _lib .c2pa_signer_reserve_size (self ._signer )
19061960
0 commit comments