C API PyErr_Clear vs PyObject_HasAttrString

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Robin Becker

    C API PyErr_Clear vs PyObject_HasAttrString

    I'm trying to understand why this code causes a seg fault second time
    through; the code is part of a setattr and is testing if the value is an
    integer or has red, green and blue attributes. This code later goes on
    to raise a ValueError if that's not the case.

    if((i = PyArg_Parse(val ue,"i",&cv))){
    c->value = cv;
    c->valid = 1;
    return 1;
    }

    rgb = PyObject_HasAtt rString(value," red")
    && PyObject_HasAtt rString(value," green")
    && PyObject_HasAtt rString(value," blue");
    PyErr_Clear();


    ........
    PyErr_SetString (PyExc_ValueErr or, "bad color value");


    Both calls should fail and raise ValueError, but the second call causes
    a seg fault in Python 2.3.4 (not in 2.2 and earlier).

    In 2.3.4 I found that moving the PyErr_Clear() before the calculation of
    rgb fixes the problem.

    I assume the problem is that something in the rgb calculation is failing
    because the python error flag is set. Is that a bug in the
    implementation of PyObject_HasAtt rString or is it my fault for not
    knowing which API calls need a cleared error flag?
    --
    Robin Becker
  • Andrew MacIntyre

    #2
    Re: C API PyErr_Clear vs PyObject_HasAtt rString

    On Sat, 27 Nov 2004, Robin Becker wrote:
    [color=blue]
    > I'm trying to understand why this code causes a seg fault second time
    > through; the code is part of a setattr and is testing if the value is an
    > integer or has red, green and blue attributes. This code later goes on
    > to raise a ValueError if that's not the case.
    >
    > if((i = PyArg_Parse(val ue,"i",&cv))){
    > c->value = cv;
    > c->valid = 1;
    > return 1;
    > }
    >
    > rgb = PyObject_HasAtt rString(value," red")
    > && PyObject_HasAtt rString(value," green")
    > && PyObject_HasAtt rString(value," blue");
    > PyErr_Clear();
    >
    >
    > ......
    > PyErr_SetString (PyExc_ValueErr or, "bad color value");
    >
    >
    > Both calls should fail and raise ValueError, but the second call causes
    > a seg fault in Python 2.3.4 (not in 2.2 and earlier).
    >
    > In 2.3.4 I found that moving the PyErr_Clear() before the calculation of
    > rgb fixes the problem.
    >
    > I assume the problem is that something in the rgb calculation is failing
    > because the python error flag is set. Is that a bug in the
    > implementation of PyObject_HasAtt rString or is it my fault for not
    > knowing which API calls need a cleared error flag?[/color]

    Rule: if you call a Python API function, _always_ check its return
    status (unless documented as void). if it fails, check for an
    exception. if you want to ignore the exception, clear the
    exception, otherwise cleanup and bailout.

    This is a paraphrase (from memory) of a previous reply from Tim Peters.

    Notwithstanding this, segfaulting in a Python API function is not welcome
    (especially one documented as always succeeding!).

    I had a look at the source (from a CVS checkout this morning), and the
    only thing that looks like a source of such trouble would be an extension
    class with a tp_getattr implementation.

    If you are using such a beast, you might want to look at the tp_getattr
    implementation first. Otherwise I'd suggest filing a bug report on SF.
    BTW, have you tried this with 2.4c1?

    -------------------------------------------------------------------------
    Andrew I MacIntyre "These thoughts are mine alone..."
    E-mail: andymac@bullsey e.apana.org.au (pref) | Snail: PO Box 370
    andymac@pcug.or g.au (alt) | Belconnen ACT 2616
    Web: http://www.andymac.org/ | Australia

    Comment

    • Robin Becker

      #3
      Re: C API PyErr_Clear vs PyObject_HasAtt rString

      Andrew MacIntyre wrote:
      ......[color=blue]
      >
      > Rule: if you call a Python API function, _always_ check its return
      > status (unless documented as void). if it fails, check for an
      > exception. if you want to ignore the exception, clear the
      > exception, otherwise cleanup and bailout.
      >
      > This is a paraphrase (from memory) of a previous reply from Tim Peters.
      >
      > Notwithstanding this, segfaulting in a Python API function is not welcome
      > (especially one documented as always succeeding!).
      >
      > I had a look at the source (from a CVS checkout this morning), and the
      > only thing that looks like a source of such trouble would be an extension
      > class with a tp_getattr implementation.[/color]

      It is such a beast, but the exciting test case looks like

      ############### ######
      import _test
      g=_test.gstate( )

      for a in ('strokeColor', 'strokeColor'):
      try:
      setattr(g,a,(1, 2,3))
      print 'Wrong handling of bad '+a
      except ValueError:
      pass
      ############### ######

      so the tp_getattr slot isn't being used.[color=blue]
      >
      > If you are using such a beast, you might want to look at the tp_getattr
      > implementation first. Otherwise I'd suggest filing a bug report on SF.
      > BTW, have you tried this with 2.4c1?[/color]

      Can't today, but I'll try and build the cut down extension with 2.4c1
      tomorrow.
      --
      Robin Becker

      Comment

      • Andrew MacIntyre

        #4
        Re: C API PyErr_Clear vs PyObject_HasAtt rString

        On Sun, 28 Nov 2004, Robin Becker wrote:
        [color=blue][color=green]
        > > I had a look at the source (from a CVS checkout this morning), and the
        > > only thing that looks like a source of such trouble would be an extension
        > > class with a tp_getattr implementation.[/color]
        >
        > It is such a beast, but the exciting test case looks like
        >
        > ############### ######
        > import _test
        > g=_test.gstate( )
        >
        > for a in ('strokeColor', 'strokeColor'):
        > try:
        > setattr(g,a,(1, 2,3))
        > print 'Wrong handling of bad '+a
        > except ValueError:
        > pass
        > ############### ######
        >
        > so the tp_getattr slot isn't being used.[/color]

        Referring to the original C code you posted, PyObject_HasAtt rString() will
        call the tp_getattr routine, clearing any exceptions raised as it returns.

        -------------------------------------------------------------------------
        Andrew I MacIntyre "These thoughts are mine alone..."
        E-mail: andymac@bullsey e.apana.org.au (pref) | Snail: PO Box 370
        andymac@pcug.or g.au (alt) | Belconnen ACT 2616
        Web: http://www.andymac.org/ | Australia

        Comment

        Working...