On 7/8/11 1:53 AM, Richard Tew wrote:
On Thu, Jul 7, 2011 at 10:10 PM, Hussain Bohra
<[email protected]>  wrote:
Hi Christian,

Thanks for your feedback.

Could you kindly let us know when you are done with the changes, so that we
can complete the existing tasks that are dependent on this fix.
Can't you work around it?  Like check if a frame is a cframe and skip
it, if it is the case?  I haven't looked at the traceback generation
in detail, but I imagine that something along the following lines
would work..

lastTasklet = stackless.current
thisTasklet = lastTasklet.next
while True:
     thisFrame = thisTasklet.frame
     while thisFrame is not None:
         if not isinstance(thisFrame, stackless.cframe):
             # Do traceback related stuff.
         thisFrame = thisFrame.f_back
     thisTasklet = thisTasklet.next
     if lastTasklet is thisTasklet:
         break

Hi Richard, Hussain,

yes, I had a look now, and you are right. CFrames get into the way,
but are a small problem. Your workaround should be a simple quick
solution in the first place, and I encourage Hussain to try that first.
It is a really simple patch to traceback.py: insert a check into extract_stack
before "if limit is None:":

    while f and not isinstance(f, types.FrameType):
        f = f.f_back

That should do.

---------------------------------------------
Now to the omission in stackless:
The special treatment of cframes is quite limited in stackless:

- sys._getframe has a patch to skip over anything that is no normal frame.
- frame objects have a getter function frame_getback() instead of the f_back
   field.

The only way how the treatment of cframes might be circumvented
in extract_stack is when a cframe is given as an argument, and that
was the omission in stackless:
tasklet.frame exposes whatever it has to the user. Only for the running
tasklet, this gets redirected to the threadstate's frame, which in the
from python visible context never is a cframe.

The function slp_get_frame is the culprit (stackless_util.c):

/* CAUTION: This function returns a borrowed reference */
PyFrameObject *
slp_get_frame(PyTaskletObject *task)
{
    PyThreadState *ts = PyThreadState_GET();

    return ts->st.current == task ? ts->frame : task->f.frame;
}

This is correct for builtin API functions, but not for the python
interface. The getter methon tasklet_get_frame (taskletobject.c)
should skip over cframes.

static PyObject *
tasklet_get_frame(PyTaskletObject *task)
{
    PyObject *ret = (PyObject*) slp_get_frame(task);

    if (ret == NULL) ret = Py_None;
    Py_INCREF(ret);
    return ret;
}

I think something like the following should do it:

static PyObject *
tasklet_get_frame(PyTaskletObject *task)
{
    PyFrameObject *f = (PyFrameObject *) slp_get_frame(task);
    PyObject *ret;

    while (f != NULL && !PyFrame_Check(f)) {
            f = f_fback;
    }
    ret = (PyObject *) f;

    if (ret == NULL) ret = Py_None;
    Py_INCREF(ret);
    return ret;
}


Not yet tested, but I guess that should do it.
Do you want to try when removing tasklet_become, or should I?

cheers -- chris

--
Christian Tismer             :^)<mailto:[email protected]>
tismerysoft GmbH             :     Have a break! Take a ride on Python's
Johannes-Niemeyer-Weg 9A     :    *Starship* http://starship.python.net/
14109 Berlin                 :     PGP key ->  http://wwwkeys.pgp.net/
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?   http://www.stackless.com/


_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless

Reply via email to