[Pyrex] my pyx module core dumps
Brandon Long
blong at fiction.net
Sat Oct 11 01:45:28 CEST 2003
I'm trying to use pyrex to speed up some existing code, and the module
dumped core on me.
I was able to get a reduced case, in the file bug.pyx. Its essentially
a class which contains a dictionary but I can access the dictionary via
attributes, ie: obj.foo is the same as obj["foo"]
The core dump occurs in the finally clause of the __getattr__ method of
the GetAttrClass class. The generated code for the finally clause looks
like this:
/*finally:*/ {
int __pyx_why;
PyObject *__pyx_3, *__pyx_1, *__pyx_4;
int __pyx_2;
__pyx_why = 0; goto __pyx_L5;
__pyx_L3: __pyx_why = 3; goto __pyx_L5;
__pyx_L4: {
__pyx_why = 4;
Py_XDECREF(__pyx_3); __pyx_3 = 0;
Py_XDECREF(__pyx_1); __pyx_1 = 0;
PyErr_Fetch(&__pyx_3, &__pyx_1, &__pyx_4);
__pyx_2 = __pyx_lineno;
goto __pyx_L5;
}
__pyx_L5:;
The core dump occurs on the Py_XDECREF of __pyx_3, which is a non-zero
value, but not a useful value.
As it happens, __pyx_3 is the return value of the recursive call to this
__getattr__ function from the attempt to access self.bar. It was 0,
which caused the goto to __pyx_L4, but its value was not 0 there.
Note that the PyObject declaractions shadow declarations from the top
level of the function. Commenting out those declarations and
re-compiling causes the bug_test program to complete with the expected
exception.
I'm not sure if this is a compiler bug, if you intended to shadow the
declarations, or what. This happens to be a rh6.2 box, with python2.2
and gcc 2.91.66 (egc-1.1.2), but had similar problems on a rh9 box with
python2.2.2 and gcc 3.2.2.
Brandon
--
"Cui merda tollenda erit?"
http://www.fiction.net/blong/
-------------- next part --------------
class GetAttrClass:
__instance_data_locked = 0
def __init__(self):
self._inside_getattr = 0 # stop recursive __getattr__
self._gone = 0
self._values = {}
self.__instance_data_locked = 1
def __getattr__(self, key):
if self._inside_getattr:
raise "recursively called __getattr__ (%s)" % (key)
try:
self._inside_getattr = 1
# This line causes a pyrex core dump, since this bar doesn't exist
# so __getattr__ is called recursively and the exception is raised
foo = self.bar
return self[key]
finally:
self._inside_getattr = 0
def __setattr__(self, key, val):
if not self.__instance_data_locked:
self.__dict__[key] = val
else:
if self.__dict__.has_key(key):
self.__dict__[key] = val
else:
self._values[key] = val
## -- dict emulation --
def __getitem__(self, key):
if self._gone:
raise "done"
return self._values[key]
def __setitem__(self, key, value):
if self._gone:
raise "done"
self._values[key] = value
-------------- next part --------------
#!/neo/opt/bin/python
import bug
## -----------------------------------------------------------------------
## T E S T S
## -----------------------------------------------------------------------
def TEST():
foo = bug.GetAttrClass()
foo.bar = "baz"
print foo.bar
print foo["bar"]
if __name__ == "__main__":
TEST()
More information about the Pyrex
mailing list