<!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" &lt;</FONT><A 
href="mailto:osuchw@ecn.ab.ca"><FONT face=Arial 
size=2>osuchw@ecn.ab.ca</FONT></A><FONT face=Arial size=2>&gt;</FONT></DIV>
<DIV><FONT face=Arial size=2>To: &lt;</FONT><A 
href="mailto:zope3-dev@zope.org"><FONT face=Arial 
size=2>zope3-dev@zope.org</FONT></A><FONT face=Arial size=2>&gt;</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>&gt; Since there seems to be an increased interest 
on the list in Zope3 on<BR>&gt; Windows tests result I am<BR>&gt; posting an 
error that I have seen showing up for quite a while.<BR></FONT></DIV>
<DIV><FONT face=Arial size=2>&gt; 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>&nbsp;</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>&nbsp;</DIV>
<DIV><FONT face=Courier size=2>&nbsp;&nbsp;&nbsp; def 
test_descr_abuse(self):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def 
abuse():<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
def foo(): 
pass<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
ContextMethod(ContextMethod(foo)).__get__(1)<BR>&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;</DIV></FONT>
<DIV><FONT face=Courier size=2>&nbsp;&nbsp;&nbsp; def 
test_descr_abuse(self):<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; def 
abuse():<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
def foo(): pass<BR>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
adebug = 
ContextMethod(foo)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
bdebug = 
ContextMethod(adebug)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
bdebug.__get__(1)</FONT></DIV>
<DIV><FONT face=Courier 
size=2>&nbsp;&nbsp;&nbsp;&nbsp;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>&nbsp;</DIV>
<DIV><FONT face=Courier size=2>static int<BR>cm_init(PyObject *self, PyObject 
*args, PyObject *kwds)<BR>{<BR>&nbsp;&nbsp;&nbsp; ContextMethod *cm = 
(ContextMethod *)self;<BR>&nbsp;&nbsp;&nbsp; PyObject *callable;</FONT></DIV>
<DIV><FONT face=Courier></FONT>&nbsp;</DIV>
<DIV><FONT face=Courier size=2>&nbsp;&nbsp;&nbsp; if (!PyArg_UnpackTuple(args, 
"ContextMethod", 1, 1, 
&amp;callable))<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 
-1;<BR>&nbsp;&nbsp;&nbsp; if (!PyCallable_Check(callable)) 
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PyErr_Format(PyExc_TypeError, 
"'%s' object is not 
callable",<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
callable-&gt;ob_type-&gt;tp_name);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
return -1;<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; 
Py_INCREF(callable);<BR>&nbsp;&nbsp;&nbsp; cm-&gt;cm_callable = 
callable;<BR>&nbsp;&nbsp;&nbsp; return 0;<BR>}<BR></FONT></DIV>
<DIV><FONT face=Courier size=2><FONT face=Arial>The&nbsp;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>&nbsp;</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>&nbsp;</DIV>
<DIV><FONT face=Courier size=2>&nbsp;&nbsp;&nbsp; return 
x-&gt;ob_type-&gt;tp_call != NULL;</FONT></DIV>
<DIV><FONT face=Courier size=2></FONT>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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>&nbsp;</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>