<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=iso-8859-1">
<META content="MSHTML 6.00.2800.1276" name=GENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY>
<DIV><FONT face=Arial size=2>----- Original Message ----- </FONT></DIV>
<DIV>
<DIV><FONT face=Arial size=2>From: "W.Osuch" <</FONT><A
href="mailto:osuchw@ecn.ab.ca"><FONT face=Arial
size=2>osuchw@ecn.ab.ca</FONT></A><FONT face=Arial size=2>></FONT></DIV>
<DIV><FONT face=Arial size=2>To: <</FONT><A
href="mailto:zope3-dev@zope.org"><FONT face=Arial
size=2>zope3-dev@zope.org</FONT></A><FONT face=Arial size=2>></FONT></DIV>
<DIV><FONT face=Arial size=2>Sent: Wednesday, January 14, 2004 1:05
AM</FONT></DIV>
<DIV><FONT face=Arial size=2>Subject: [Zope3-dev] Zope3+W2k+mingw=Python
crash</FONT></DIV></DIV>
<DIV><FONT face=Arial><BR><FONT size=2></FONT></FONT></DIV>
<DIV><FONT face=Arial size=2>> Since there seems to be an increased interest
on the list in Zope3 on<BR>> Windows tests result I am<BR>> posting an
error that I have seen showing up for quite a while.<BR></FONT></DIV>
<DIV><FONT face=Arial size=2>> test_descr_abuse
(zope.context.tests.test_wrapper.WrapperTestCase) ...<BR></FONT></DIV>
<DIV><FONT face=Arial size=2>I've analyzed this failure down into the C code and
understand why it fails. But it leaves three questions to be
answered...</FONT></DIV>
<DIV><FONT face=Arial size=2>1) Why is the failure only manifested on Windows
(XP in my case) and mingw32?</FONT></DIV>
<DIV><FONT face=Arial size=2>2) Is the unit test wrong (as I describe
below)?</FONT></DIV>
<DIV><FONT face=Arial size=2>3) Is the wrapper.c code incorrect?</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Arial size=2>The abort does occur in the test_descr_abuse unit
test at the ContextMethod() call. The current code looks like this:</FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Courier size=2> def
test_descr_abuse(self):<BR> def
abuse():<BR>
def foo():
pass<BR>
ContextMethod(ContextMethod(foo)).__get__(1)<BR> self.assertRaises(TypeError,
abuse)<BR></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>Breaking it down a bit further,
I found that it's the second ContextMethod() call which triggers the
failure.</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT> </DIV></FONT>
<DIV><FONT face=Courier size=2> def
test_descr_abuse(self):<BR> def
abuse():<BR>
def foo(): pass<BR>
adebug =
ContextMethod(foo)<BR>
bdebug =
ContextMethod(adebug)<BR>
bdebug.__get__(1)</FONT></DIV>
<DIV><FONT face=Courier
size=2> self.assertRaises(TypeError, abuse)<BR><BR><FONT
face=Arial>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.</FONT></FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Courier size=2>static int<BR>cm_init(PyObject *self, PyObject
*args, PyObject *kwds)<BR>{<BR> ContextMethod *cm =
(ContextMethod *)self;<BR> PyObject *callable;</FONT></DIV>
<DIV><FONT face=Courier></FONT> </DIV>
<DIV><FONT face=Courier size=2> if (!PyArg_UnpackTuple(args,
"ContextMethod", 1, 1,
&callable))<BR> return
-1;<BR> if (!PyCallable_Check(callable))
{<BR> PyErr_Format(PyExc_TypeError,
"'%s' object is not
callable",<BR>
callable->ob_type->tp_name);<BR>
return -1;<BR> }<BR>
Py_INCREF(callable);<BR> cm->cm_callable =
callable;<BR> return 0;<BR>}<BR></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>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.</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>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.</FONT></FONT></DIV>
<DIV><FONT face=Arial size=2></FONT> </DIV>
<DIV><FONT face=Courier size=2> return
x->ob_type->tp_call != NULL;</FONT></DIV>
<DIV><FONT face=Courier size=2></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>So, back to the three
questions:</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>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.</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>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?</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>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.</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>I could really use some insight
at this point.</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial></FONT></FONT> </DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>Thanks,</FONT></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>Dave
Harris</DIV></FONT></FONT></BODY></HTML>