-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
MAINT: _lib: add __dealloc__ to MessageStream #14328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Extension class `MessageStream` doesn't implement a `__dealloc__` method which is required to free C level structures once the object goes out of scope. It is possible to do so with a call to the `close()` method but it is very inconvenient to call it every time one doesn't need the message stream anymore. Also, there could be a memory leak if one forgot to call the `close` method. Using `__dealloc__`, we can tell Cython to manage memory automatically for us.
scipy/_lib/messagestream.pyx
Outdated
@@ -88,3 +88,15 @@ cdef class MessageStream: | |||
if not self._removed: | |||
stdio.remove(self._filename) | |||
self._removed = 1 | |||
|
|||
def __dealloc__(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you just rename __del__
to __dealloc__
? You might also have to change def close
to cpdef close
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you just rename
__del__
to__dealloc__
?
Yes, in fact, we should do this. From the documentation:
Note: There is no __del__() method for extension types
You might also have to change
def close
tocpdef close
That sounds right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
cd81c18
to
c4df649
Compare
There's still something that looks weird. As the Cython docs say, The first part of self._memstream_ptr = NULL
self.handle = messagestream_open_memstream(&self._memstream_ptr,
&self._memstream_size) Potential issues:
|
I don't think that should happen because the variable
I think you are right here. According to Cython docs, its best to put all the C level initialization code in Update: I tried to do this and I get a RuntimeWarning during build and import: |
Hmm interesting. I'm not entirely sure. Let's see if someone else who actually understands what Cython is doing under the hood will comment. |
Never mind the warning. I had to rebuild scipy from scratch. I think Cython was just picking up between the conflicting code generated by previous version of MessageStream that had the |
@@ -40,7 +40,7 @@ cdef class MessageStream: | |||
if stdio.remove(self._filename) == 0: | |||
self._removed = 1 | |||
|
|||
def __del__(self): | |||
def __dealloc__(self): | |||
self.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the docs:
In particular, don’t call any other methods of the object or do anything which might cause the object to be resurrected. It’s best if you stick to just deallocating C data.
This is probably fine as close()
is cpdef
'd and thus as a C version is available even if the Python class is in an invalid state
This looks like a good change to me and a win for low-level memory management safety. If there are no further comments, I'll plan on merging this later this evening |
Thanks @mckib2 for the review! |
Reference issue
N/A
What does this implement/fix?
Extension class
MessageStream
doesn't implement a__dealloc__
method which is required to free C level structures once the object goes out of scope. It is possible to do so with a call to theclose()
method but it is very inconvenient to call it every time one doesn't need the message stream anymore. Also, there could be a memory leak if one forgot to call theclose
method. Using__dealloc__
, we can tell Cython to manage memory automatically for us.Additional information
This is not in the public API but I was planning to use this in #14215 for error handling and it would help if this method was present.