Thank you for your comments!
On 6/10/2010 3:40 PM, Kristján Valur Jónsson wrote:
The fact that you are using Sleep() there indicates to me either
a) a misunderstanding or
b) you don't hold the python GIL at this point.
It seems possible that on a loaded system, the worker thread could be
scheduled right after the queue call, but before the
PyStackless_Schedule(). This will always result in a deadlock when the
worker calls PyTasklet_Insert() before the OS can reschedule the
original thread so the _Schedule() call can occur ie:
Thread A Thread B
q up request
<preempt>
service request, wake up
tasklet [which has not gone to sleep yet!]
<preempt>
go to sleep with _Schedule,
waiting for _Insert call
<deadlock>
Placing a breakpoint on that line it never hits, and I don't expect
under normal circumstances it ever will, but with heavy stress its possible.
How are you manging the GIL? You must be releasing it at some point to deal with your
"request", otherwise this whole excercise wouldn't be worthwhile.
I didn't think I needed to acquire it for this, but just to test (refer
to the other email I sent out on this subject) I tried:
PyEval_AcquireLock();
PyTasklet_Insert( request->tasklet );
PyEval_ReleaseLock();
and it still crashes on the _insert instantly, as soon as the program is
invoked, but adding:
PyEval_AcquireLock();
Sleep(2);
PyTasklet_Insert( request->tasklet );
PyEval_ReleaseLock();
Allows it to run for quite awhile before dying (actually only just now a
test died, up until then I thought it was a complete workaround)
Again to emphasize- the Sleep() is there because I am forcing the task
to complete trivially and return, as a test. In other words as soon as
the worker thread wakes up on the queue entry, it immediately completes
and tries to wake up the caller. *crash* What it feels like is that
stackless needs to do <something> after that _Schedule() call and if
that <something> is not allowed to complete, an _Insert on the same
tasklet dies. otherwise everything works. Although I am still wondering
how I am going to ensure thread safety with the _Schedule call, since it
doesn't return to the calling stack when it swaps. but one thing at a time.
-----Original Message-----
From: [email protected] [mailto:stackless-
[email protected]] On Behalf Of Chris
Sent: 10. júní 2010 15:46
To: [email protected]
Subject: [Stackless] Putting apps to sleep and waking them up from the
API
I must be doing something silly and wrong, hopefully I can get some
help
from this list. I am writing a blocking call in the c api which is
serviced by a [pool] of other threads, of course when the call is made
I
want to let stackless continue processing, so I did this, which works
great:
PyObject* getData(PyObject *self, PyObject *args)
{
// blah blah construct request on the heap
request->task = PyStackless_GetCurrent();
queueRequest( request ); // this will get picked up by the thread
pool
PyStackless_Schedule( request->task ); // away it goes back into
python-land
Py_DECREF( request->task ); // if we got here its because we were
woken up
// blah blah construct response and return
}
The thread pool does this:
worker()
{
// blah blah wait on queue and get a job and do some work
waiting for awhile (or returning immediately)
while( !PyTasklet_Paused(request->task) ) // prevent race
(deadlock if this runs before the _Schedule call)
{
Sleep(0); // yield
}
PyTasklet_Insert( request->task );
}
This works just fine. Until I stress it. this program from python
crashes instantly in unpredicatbale (corrupt memory) ways:
import stackless
import dbase
def test():
while 1:
dbase.request()
for i in range( 10 ):
task = stackless.tasklet( test )()
while 1:
stackless.schedule()
BUT if I change that range from 10 to 1? runs all day long without any
problems. Clearly I am doing something that isn't thread safe. but
what?
I've tried placing mutexes around the PyTask_ calls but since schedule
doesn't normally return thats not possible everywhere, If I add Sleep's
it helps, in fact if I make them long enough it fixes the problem and
all 10 threads run concurrently.
I assume PyTasklet_Schedule()/_Insert() are meant to be used this way,
(ie- multiple threads) can anyone tell me which stupid way I have gone
wrong?
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless