[ZODB-Dev] Latest news: core dump with small change to POSException.py

Greg Ward gward@mems-exchange.org
Thu, 4 Oct 2001 14:17:08 -0400


On 26 September 2001, I said:
> Is this as simple as recursively grep'ing for "ConflictError" in
> StandaloneZODB/.../*.c, and inspecting the code found in the
> neighbourhood of that identifier being used?  If so, I'll take a crack
> at it -- looks like it only happens in a handful of places.

OK, I've started looking into how ConflictError is raised in the ZODB C
code.  It looks like it's only done in three source files:

  BTrees/BTreeTemplate.c
  BTrees/BucketTemplate.c
  BTrees/MergeTemplate.c

...and it's only done in one place in each of those files.  Good.

BTreeTemplate.c does this, in BTree__p_resolveConflict

err:

  if (r) {
  	ASSIGN(r, Py_BuildValue("((O))", r));
  } else {
  	PyObject *error;
	PyObject *value;
	PyObject *traceback;
  	/* Change any errors to ConflictErrors */

        /* XXX need to change this -GW */
	PyErr_Fetch(&error, &value, &traceback);
	Py_INCREF(ConflictError);
	Py_XDECREF(error);
	PyErr_Restore(ConflictError, value, traceback);
  }

>From reading the Python C API manual, I believe the "else" clause is the
moral equivalent of this:

  except:
    (error, value, traceback) = sys.excinfo()
    raise ConflictError, value, traceback

...which seems like a rather strange thing to me, but what do I know?

Anyways, this is problematic because the ConflictError constructor gets
involved, and I have changed that constructor's signature from the
default Exception constructor:
  def __init__ (self, *args)
to
  def __init__ (self [, message [, object [, serials]]])

and passing some arbitrary exception object to this cause a TypeError.
(The coredump in testConflict.py has been worked around by qualifying an
unqualified "except".)

I'm not sure of the best way to fix this.  The most obvious is to do the
C equivalent of this:
  except:
    (error, value, traceback) = sys.excinfo()
    raise ConflictError(str(value)), traceback

-- ie. don't pass an arbitrary exception object to the ConflictError
constructor, instead use its stringification as the ConflictError's
message.

It'll take me a while to learn how to do this in C, but I'm sure it
won't be too hard.  But before I do, does this sound like the right way
to fix this code?

(BTW, the ConflictError raise in BucketTemplate.c is quite similar to
this one, so the same solution should apply.  I haven't figured out what
to do about the one in MergeTemplate.c yet.)

        Greg
-- 
Greg Ward - software developer                gward@mems-exchange.org
MEMS Exchange                            http://www.mems-exchange.org