On Nov 24, 2009, at 3:43 PM, Kristján Valur Jónsson wrote:
> Yes, what you describe sounds like a fair normal scenario and is precisely
> what the cstack's "serial" member is supposed to make work.
>
> Now, in the first "main", that main tasklet returns. You then enter a second
> "main" and when this is returning, it does an incorrect slp_transfer_return,
> somehow.
>
> It is this last bit that is hard to understand, because it is difficult to
> see how it can be wrong. The code is simple:
>
> PyTaskletObject *task = ts->st.current;
> int ismain = task == ts->st.main;
>
> ...
>
> if (ismain) {
> if (ts->st.serial_last_jump != ts->st.serial) {
> slp_transfer_return(task->cstate);
>
> So, the slp_transfer_return is only triggered if indeed it is _the_ main
> tasklet (the last "main" tasklet) that is returning. And an
> slp_transfer_return() should be safe, because it will switch to the place
> where this tasklet created its initial stub, even if we are already on the
> correct stack. If you follow the code through the debugger right past the
> actual stack switch, you should find yourself in make_initial_stub.
No... I find myself several levels down in slp_schedule_task inside
PyStackless_RunWatchdogEx...
so the slp_transfer_return is bad, since at this point ts->frame has been
cleared (==0) and there
are no frames to pop to get back up (this is the cause of the crash). However
why am I there?
I don't know... coincidentally it is the place of the previous transfer into
(and out of) the main tasklet...
>
> Are you working on windows?
No. OS-X at the moment... but I have to get it to work "everywhere"...
I have a small failing test, see below...
> Now, I'm quite curious as to why your bug is happening, and we should fix it,
> but if all else fails, there is a workaround. This is the workaround that we
> have employed in EVE for years, since before the time when multiple "main"
> tasklets became possible: At the start of your program, enter a "main"
> context and stay there, by using PyStackless_Call_Main, having exposed your
> program's stackless_main function to python as a c function. Then you stay
> within a main tasklet. Something like
Hm... that appears to have the same problem (if I understand it, it maybe just
avoids some overhead on
the main tasklet)
I have, just now, boiled it down to a test program that crashes:
test1.c
--------------------------------------------------
#include <Python.h>
int main(int argc, char *argv[]) {
PyObject* globals = 0, *m, *f;
Py_InitializeEx(0);
m = PyImport_AddModule("__main__");
if(m) globals = PyModule_GetDict(m);
if((f =
PyRun_String("execfile('./test1.py')",Py_file_input,globals,globals))) {
Py_DECREF(f);
f = PyDict_GetItemString(globals, "my_entry");
if(f && PyCallable_Check(f)) {
int i;
PyObject* args = PyTuple_New(0);
printf("Got callable to test...calling 10 times...");
for(i=0; i<10; i++) {
printf("Calling %d\n",i);
PyObject *r
/*either way crashes*/
#if 0
= PyStackless_Call_Main(f, args, NULL);
#else
= PyObject_CallObject(f, args);
#endif
}
}
}
}
test1.py
--------------------------------------------------
import stackless
def forever():
while 1: pass
tlist = []
i = 0
def my_entry():
global i
if i == 0:
tlist.append(stackless.tasklet(forever)())
else:
t = stackless.run(1000)
print "Run returned",t
i += 1
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless