[Zope3-dev] Zope3+W2k+mingw=Python crash

David Harris dpharris76 at msn.com
Fri Jan 16 01:44:22 EST 2004


----- Original Message ----- 
From: "W.Osuch" <osuchw at ecn.ab.ca>
To: <zope3-dev at zope.org>
Sent: Wednesday, January 14, 2004 1:05 AM
Subject: [Zope3-dev] Zope3+W2k+mingw=Python crash


> Since there seems to be an increased interest on the list in Zope3 on
> Windows tests result I am
> posting an error that I have seen showing up for quite a while.

> test_descr_abuse (zope.context.tests.test_wrapper.WrapperTestCase) ...

I've analyzed this failure down into the C code and understand why it fails. But it leaves three questions to be answered...
1) Why is the failure only manifested on Windows (XP in my case) and mingw32?
2) Is the unit test wrong (as I describe below)?
3) Is the wrapper.c code incorrect?

The abort does occur in the test_descr_abuse unit test at the ContextMethod() call. The current code looks like this:

    def test_descr_abuse(self):
        def abuse():
            def foo(): pass
            ContextMethod(ContextMethod(foo)).__get__(1)
    self.assertRaises(TypeError, abuse)

Breaking it down a bit further, I found that it's the second ContextMethod() call which triggers the failure.

    def test_descr_abuse(self):
        def abuse():
            def foo(): pass
            adebug = ContextMethod(foo)
            bdebug = ContextMethod(adebug)
            bdebug.__get__(1)
    self.assertRaises(TypeError, abuse)

ContextMethod resides in wrapper.c. cm_init() sets the stage for the failure which is subsequently realized in cm_dealloc(). And here's where the questionable things come in.

static int
cm_init(PyObject *self, PyObject *args, PyObject *kwds)
{
    ContextMethod *cm = (ContextMethod *)self;
    PyObject *callable;

    if (!PyArg_UnpackTuple(args, "ContextMethod", 1, 1, &callable))
        return -1;
    if (!PyCallable_Check(callable)) {
        PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
             callable->ob_type->tp_name);
        return -1;
    }
    Py_INCREF(callable);
    cm->cm_callable = callable;
    return 0;
}

The ContextMethod(adebug) call results in PyCallable_Check() returning 0, which leads to PyErr_Format() and a return value of -1. The initialization of the resulting ContextMethod object (bdebug) is incomplete and cm_dealloc() aborts when trying to handle the debris.

Why does PyCallable_Check() fail? Because the tp_call field is not set for ContextMethod object adebug. I traced into PyCallable_Check() (which is in Python23's object.c file) and found that the following line of code was exercised and returned 0.

    return x->ob_type->tp_call != NULL;

So, back to the three questions:

1) I don't see anything Windows-specific here. The empty tp_call field should be happening on all systems. However, it could be that cm_dealloc() survives the encounter with bdebug on *NIX systems, where Windows is less forgiving. Purely conjecture, I don't know for sure.

2 and 3) The abuse() method does not (cannot??) check for a failure in ContextMethod(). I'm still new enough to Python that I can't begin to suggest how the event should be resolved. The real issue is how cm_dealloc() is invoked - does it happen when cm_init() fails or when abuse() exits?

The situation really boils down to this: I can't tell if the empty tp_call field is intentional or not. That ContextMethod is a method seems to imply that it is callable and tp_call should be set. At the same time, the wrapper unit tests have been running fine for somebody which implies that ContextMethod is operating within normal parameters.

I could really use some insight at this point.

Thanks,
Dave Harris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.zope.org/pipermail/zope3-dev/attachments/20040116/98540c0a/attachment.html


More information about the Zope3-dev mailing list