fix: __del__ not freeing up native resources#38
Conversation
When Plugin creates its own CompiledPlugin internally, it should also free it in __del__. Added _owns_compiled_plugin flag to track ownership and avoid freeing externally-passed CompiledPlugin instances. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
|
@nilslice in case you can take a look, thanks! |
Restructure Plugin.__init__ to make compiled_plugin ownership more explicit with type annotation, and apply consistent formatting to tests.
|
@acoroleu-tempus - thanks for this! did a quick pass on the PR and after updating some minor internals and fixing a lint error this should be good to go. if you'd like to take a look at 9a156f1, please do - otherwise I'll merge this in tomorrow or early next week. |
|
@nilslice thanks for the changes, looks good to merge. Would you create a release right after? |
|
@nilslice can we merge this and create a release? thanks |
|
@nilslice the released failed: https://github.com/extism/python-sdk/actions/runs/22148685889/job/64033396027 |
|
@acoroleu-tempus yea, I saw - I don't have time unfortunately to debug it today so I'll get to it asap |
|
@acoroleu-tempus - new release is in progress, the build should work - but let me know if you have any issues. Thanks! |
extism/extism#890
Summary
Fix memory leaks caused by del methods not properly freeing native resources.
Bug 1:
Plugin.__del__never calledextism_plugin_freeThe guard check used hasattr(self, "pointer") but Plugin stores the handle in self.plugin, not self.pointer. This caused the method to
always return early, never freeing the native plugin.
Bug 2: Double-free errors in all
__del__methodsWhen del is called multiple times (e.g., via context manager exit then garbage collection), the code would attempt to free
already-freed resources, causing TypeError or segfaults.
Changes
•
Plugin.__del__: Fix attribute check ("pointer" → "plugin") and add -1 guard•
CompiledPlugin.__del__: Add -1 guard to prevent double-free•
_ExtismFunctionMetadata.__del__: Add None guard and set pointer = None after freeingImpact
This fix enables using extism in long-running services that create fresh plugin instances per request, which previously caused unbounded
memory growth.
Test plan
• Added test_plugin_del_frees_native_resources - verifies Plugin cleanup via context manager
• Added test_compiled_plugin_del_frees_native_resources - verifies CompiledPlugin cleanup
• Added test_extism_function_metadata_del_frees_native_resources - verifies function metadata cleanup
• All tests verify that del can be safely called multiple times