It is not immediately clear what would cause the crash here but you
should be clearer about what "crash" means (segfault? exception?
something else?).
I can definitely see many problems with this code though. In general I
would say that there is just way too much happening in this __cinit__
method and also too much in __dealloc__:
https://github.com/scipy/scipy/blob/v1.10.0/scipy/_lib/messagestream.pyx#L21
Messing around with files, calling into Python code, catching
exceptions etc just should not really happen in either __cinit__ or
__dealloc__.
The purpose of __cinit__ is just to leave the object with its C-level
state ready for __dealloc__ to be called safely. That does not mean
that __cinit__ necessarily needs to initialise anything to its
intended value but just that any invariants expected by __dealloc__
must be satisfied after __cinit__ exits. Usually that just means
setting everything to NULL which is actually done implicitly before
__cinit__ is called anyway. Then if __dealloc__ checks for NULL
everything is fine.
It is possible that code in __cinit__ might exit from raising an
exception in which case __dealloc__ would be called immediately so any
place where an exception could be raised is a place where all
invariants must be satisfied. If potentially calling into any Python
code then there is a possibility for an exception to be raised
(including from a signal) so the invariants must be satisfied at that
point. Basically you need to think that __dealloc__ is just something
that can happen at almost any time.
The __dealloc__ method for this class calls self.close() which in turn checks
if not self._removed
This is a poor choice of variable because the default initialisation
used by Cython will be to set _removed to False. It would be better to
invert the meaning of this boolean variable so that False is the safe
value. There are ways that __cinit__ might exit with an exception
without initialising this value including the possibility that
self._filename might be uninitialised (e.g. mkstemp or os.remove could
fail or a signal could be raised during those calls).
Also it is a mistake to try to use RAII like this in Python even when
done from Cython. It would be better for this object to be a context
manager i.e. move all the code from __cinit__ and __dealloc__ to
__enter__ and __exit__.
--
Oscar