|
From: CL <clc...@gm...> - 2009-01-19 03:33:01
|
Since I am not familar with the code of GIL, correct me if I am wrong
..as I make some fundamental guesses in the gil and locking calls.
I have this problem also on my programs. The problem looks like a
deadlock rather than overflow. Therefore, it can happen in any vpython
programs.
Here is my observations, :
The keyboard buffer queue is implemented as a atomic_queue in vpython.
It has a lock object called "barrier" to protect the queue. The
deadlock situation is like this:
Caller thread:
C1. call getkey()
C2. call py_pop()
C3. == py_pop() lock the barrier object
C4. == call py_pop_wait()
C5. == == py_pop_wait() release the gil_lock
C6. == == wait until there is some keys in the queue (during waiting,
the barrier object seems unlocked)
C7. == == regain gil_lock
C8. == == returning to py_pop()
C9. == pop a key from the queue
C10. == unlock barrier object
The primary window thread:
P1. In dispatch_messages():
P2. == gain gil_lock
P3. == for WM_KEYUP, WM_KEYDOWN, WM_CHAR, handle the key messages
P4. == == lock barrier object
P5. == == update the key queue
P6. == == unlock barrier object
P7. == release gil_lock
If the first thread is in between C5-C7 and the key queue is not
empty, at this moment user press a key, the primary window thread can
gain the gil_lock and performing a dispatching of key events, it will
try to gain the barrier lock (P4). The first thread is locked when it
is going to regain the gil_lock (C7). The primary window thread is
locked by waiting the barreir lock.
This situation does not happen frequently, because the time spend in
py_pop_wait is very short.
But I can make it happens easily when I add a delay in py_pop_wait
before it returns:
void
atomic_queue_impl::py_pop_wait( lock& L)
{
....
waiting = false;
::Sleep(100);
}
If my understanding above is correct, the program can be fixed by
rewritting the function as:
void
atomic_queue_impl::py_pop_wait( lock& L)
{
using python::gil_release;
using python::gil_lock;
L.unlock();
{
gil_release release;
// I took the code to call Py_MakePendingCalls() out. The internet leads
// me to believe that it is not necessary. For example, Python time.sleep()
// doesn't do it.
if (empty) {
L.lock();
while (empty) {
waiting = true;
ready.wait(L);
}
L.unlock();
}
waiting = false;
}
L.lock();
}
CL
>I have been looking workarounds and found that by including opacity
>during a box definition, with any value Except 1.0 allows opacity to work!
>Also, if you have nested frames then a pause before connecting the main
>frame from the sub frames works!
>Another problem that has just popped up.
>Any keyboard input that requires holding down a key for long periods
>seems to cause some programs to freeze, but not all!
>Here are 3 examples, they all use cursor keys to move or spin objects.
>It acts like a keyboard buffer overflow, but that's just a guess.
|