<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html; charset=ISO-8859-1"
 http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
<tt>This error exists since 2006. I think we introduced it on the<br>
Stackless sprint. I won't blame anybody, maybe it was me, no idea.<br>
<br>
In any case, the Stackless API is broken. PyEval_EvalFrame cannot<br>
be used.<br>
<br>
The code is working in the path<br>
<br>
<a class="moz-txt-link-abbreviated" href="mailto:svn+ssh://pythondev@svn.python.org/stackless/Python-2.4.2/src/Python/ceval.c">svn+ssh://pythondev@svn.python.org/stackless/Python-2.4.2/src/Python/ceval.c</a><br>
<br>
and broken in<br>
<br>
<a class="moz-txt-link-abbreviated" href="mailto:svn+ssh://pythondev@svn.python.org/stackless/Python-2.4.2/dev/Python/ceval.c">svn+ssh://pythondev@svn.python.org/stackless/Python-2.4.2/dev/Python/ceval.c</a><br>
<a class="moz-txt-link-abbreviated" href="mailto:svn+ssh://pythondev@svn.python.org/stackless/Python-2.4.3/dev/Python/ceval.c">svn+ssh://pythondev@svn.python.org/stackless/Python-2.4.3/dev/Python/ceval.c</a><br>
<br>
and all higher versions in branches, tags, and trunk of course.<br>
<br>
This means: nobody ever used the API explicitly since then, but me. :-)<br>
<br>
The reason why this is broken:<br>
In 2.4.2/src we had no retval parameter. It was a local, initialized to
NULL,<br>
but it was then initialized here:<br>
<br>
<font color="#3366ff">PyObject *<br>
PyEval_EvalFrame_value(PyFrameObject *f)<br>
{<br>
&nbsp;&nbsp;&nbsp; /* unfortunately we repeat all the variables here... */<br>
#ifdef DXPAIRS<br>
&nbsp;&nbsp;&nbsp; int lastopcode = 0;<br>
#endif<br>
&nbsp;&nbsp;&nbsp; register PyObject **stack_pointer;&nbsp;&nbsp; /* Next free slot in value
stack */<br>
&nbsp;&nbsp;&nbsp; register unsigned char *next_instr;<br>
&nbsp;&nbsp;&nbsp; register int opcode;&nbsp;&nbsp;&nbsp; /* Current opcode */<br>
&nbsp;&nbsp;&nbsp; register int oparg;&nbsp;&nbsp;&nbsp; /* Current opcode argument, if any */<br>
&nbsp;&nbsp;&nbsp; register enum why_code why; /* Reason for block stack unwind */<br>
&nbsp;&nbsp;&nbsp; register int err;&nbsp;&nbsp;&nbsp; /* Error status -- nonzero if error */<br>
&nbsp;&nbsp;&nbsp; register PyObject *x;&nbsp;&nbsp;&nbsp; /* Result object -- NULL if error */<br>
&nbsp;&nbsp;&nbsp; register PyObject *v;&nbsp;&nbsp;&nbsp; /* Temporary objects popped off stack */<br>
&nbsp;&nbsp;&nbsp; register PyObject *w;<br>
&nbsp;&nbsp;&nbsp; register PyObject *u;<br>
&nbsp;&nbsp;&nbsp; register PyObject *t;<br>
&nbsp;&nbsp;&nbsp; register PyObject *stream = NULL;&nbsp;&nbsp;&nbsp; /* for PRINT opcodes */<br>
&nbsp;&nbsp;&nbsp; register PyObject **fastlocals, **freevars;<br>
&nbsp;&nbsp;&nbsp; PyObject *retval = NULL;&nbsp;&nbsp;&nbsp; /* Return value */<br>
&nbsp;&nbsp;&nbsp; PyThreadState *tstate = PyThreadState_GET();<br>
&nbsp;&nbsp;&nbsp; PyCodeObject *co;<br>
<br>
&nbsp;&nbsp;&nbsp; /* when tracing we set things up so that<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; not (instr_lb &lt;= current_bytecode_offset &lt;
instr_ub)<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; is true when the line being executed has changed.&nbsp; The<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initial values are such as to make this false the first<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; time it is tested. */<br>
&nbsp;&nbsp;&nbsp; int instr_ub = -1, instr_lb = 0, instr_prev = -1;<br>
<br>
&nbsp;&nbsp;&nbsp; unsigned char *first_instr;<br>
&nbsp;&nbsp;&nbsp; PyObject *names;<br>
&nbsp;&nbsp;&nbsp; PyObject *consts;<br>
#ifdef LLTRACE<br>
&nbsp;&nbsp;&nbsp; int lltrace;<br>
#endif<br>
#if defined(Py_DEBUG) || defined(LLTRACE)<br>
&nbsp;&nbsp;&nbsp; /* Make it easier to find out where we are with a debugger */<br>
&nbsp;&nbsp;&nbsp; char *filename;<br>
#endif<br>
<br>
fast_reentry:<br>
&nbsp;&nbsp;&nbsp; retval = tstate-&gt;st.tempval;<br>
&nbsp;&nbsp;&nbsp; tstate-&gt;st.tempval = NULL;<br>
#endif /* STACKLESS */<br>
<br>
&nbsp;&nbsp;&nbsp; co = f-&gt;f_code;</font><br>
<br>
The fast_reentry case vanished without any trace, therefore pushing<br>
the burden to initialize retval to the call-sites of<br>
PyEval_EvalFrame_Value. But this never happened. And it was not<br>
recognized because the function was only called indirectly<br>
via frame-&gt;f_execute, where a value is passed in.<br>
<br>
The correction would be to either make the NULL check more<br>
careful, or to pass in a dummy object which needs no reference.<br>
In any case, this is a necessary change to un-break the<br>
Stackless API.<br>
<br>
Nevertheless, and even worse, the API is broken even more.<br>
----------------------------------------------------------<br>
<br>
An API function that has no "slp" in it is never allowed to<br>
return the Py_UnwindToken.<br>
Exactly that is possible in the end of PyEval_EvalFrame_value:<br>
<br>
<font color="#00cccc"><font color="#3366ff">stackless_interrupt_call:<br>
<br>
&nbsp;&nbsp;&nbsp; f-&gt;f_execute = PyEval_EvalFrame_noval;<br>
&nbsp;&nbsp;&nbsp; f-&gt;f_stacktop = stack_pointer;<br>
<br>
&nbsp;&nbsp;&nbsp; /* the -1 is to adjust for the f_lasti change.<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; (look for the word 'Promise' above) */<br>
&nbsp;&nbsp;&nbsp; f-&gt;f_lasti = INSTR_OFFSET() - 1;<br>
&nbsp;&nbsp;&nbsp; f = tstate-&gt;frame;<br>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return (PyObject *) Py_UnwindToken;<br>
#endif<br>
}</font><br>
<br>
</font>So the API needs a bit more protection, to really be compliant<br>
to the Python API.<br>
<br>
I came across this because I got into trouble when implementing<br>
Stackless support for Psyco. I think I can get along this by<br>
adding the necessary support functions to Psyco. This is easier<br>
right now than to consistently fix all Stackless versions.<br>
But the latter needs to be done, ASAP.<br>
<br>
cheers - chris<br>
<br>
On 4/12/10 8:36 PM, Christian Tismer wrote:</tt>
<blockquote cite="mid:4BC36827.90406@stackless.com" type="cite"><tt>There
appears to be a stackless error in release25-maint:
  <br>
  <br>
When I try to use the API call PyEval_EvalFrameEx, I always get
  <br>
a crash, because PyEval_EvalFrameEx calls
  <br>
PyEval_EvalFrameEx_slp, which does
  <br>
  <br>
&nbsp;&nbsp;&nbsp; return PyEval_EvalFrameEx_slp(f, throwflag, NULL);
  <br>
  <br>
This NULL value gets passed to
  <br>
  <br>
&nbsp;&nbsp;&nbsp; return PyEval_EvalFrame_value(f, throwflag, retval);
  <br>
  <br>
and then retval is checked: stacklesseval.c#692
  <br>
  <br>
&nbsp;&nbsp;&nbsp; /* always check for an error flag */
  <br>
&nbsp;&nbsp;&nbsp; if (retval == NULL) {
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; why = WHY_EXCEPTION;
  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto on_error;
  <br>
&nbsp;&nbsp;&nbsp; }
  <br>
  <br>
This cannot be correct, it must be possible to enter the evaluator
  <br>
with a NULL retval. Semantically it originates from a local variable
  <br>
which is initialized as NULL, so somehow the above test must be
  <br>
misplaced.
  <br>
  <br>
This blocks me at the moment because I'm confused how this error
  <br>
crept in; suffering too many versions in the moment.
  <br>
  <br>
help - chris
  <br>
  <br>
  </tt>
</blockquote>
<tt><br>
</tt><br>
<pre class="moz-signature" cols="72">-- 
Christian Tismer             :^)   <a class="moz-txt-link-rfc2396E" href="mailto:tismer@stackless.com">&lt;mailto:tismer@stackless.com&gt;</a>
tismerysoft GmbH             :     Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9A     :    *Starship* <a class="moz-txt-link-freetext" href="http://starship.python.net/">http://starship.python.net/</a>
14109 Berlin                 :     PGP key -&gt; <a class="moz-txt-link-freetext" href="http://wwwkeys.pgp.net/">http://wwwkeys.pgp.net/</a>
work +49 30 802 86 56  mobile +49 173 24 18 776  fax +49 30 80 90 57 05
PGP 0x57F3BF04       9064 F4E1 D754 C2FF 1619  305B C09C 5A3B 57F3 BF04
      whom do you want to sponsor today?   <a class="moz-txt-link-freetext" href="http://www.stackless.com/">http://www.stackless.com/</a></pre>
</body>
</html>