[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