hydpy-dev / hydpy

A framework for the development and application of hydrological models based on Python
GNU Lesser General Public License v3.0
35 stars 17 forks source link

Segmentation faults in curious Python consoles #148

Closed tyralla closed 3 months ago

tyralla commented 3 months ago

Executing the following statements within, e.g., Pycharm's Python Console results in a segfault:

from hydpy.models.hland_96 import *
parameterstep()  # Process finished with exit code -1073741819 (0xC0000005)

The reason is that Pycharm tries to find information about Cython-level arrays that have not been initialised. Hence, our current workaround is to play around in Pycharm's Python Console only in the pure Python mode:

from hydpy import pub
pub.options.usecython = False
from hydpy.models.hland_96 import *
parameterstep()  # no problem

We could avoid this problem by activating Cython's initializedcheck option when compiling the models. However, this would increase simulation time by a few percent. Hence, we thought about just discussing this problem in the online documentation, but it would be clearly better if we could solve it without losing performance.

Here is a toy example:

class A:
    @property
    def p(self):
        sys.exit(666)

a = A() 
a.  # Process finished with exit code 666

Making p private (_p) or "special" (__p__) does not help. But removing p from the dir results fixes the problem:

import sys

class A:
    @property
    def f(self):
        sys.exit(9)
    def __dir__(self):
        return [n for n in super().__dir__() if n != "f"]

a = A()
a.  # no problem

I hope 99% of all potentially uninitialised arrays are hidden behind a fastaccess attribute. Hence, we could either remove fastaccess from the __dir__ methods of classes that define a fastaccess attribute (at best, only when working in Cython mode). Or, we could remove the potentially problematic arrays (or just everything) from the __dir__ method of all FastAccess classes (at best, only from the Cython extension classes).

tyralla commented 3 months ago

While working on it, I found a bug that I fixed in b7b1d196b7cc51449947bd91d879036b64f8e94a.

Overwriting __dir__ (as discussed) above or initialising all arrays with None or a zero-length array (as discussed with @holgeralbert) could give us additional safety. However, we should only do this if we find that additional protection is required.