Preventing PyEval_AcquireLock deadlock
Is there an easy way in the API to check if the current thread already has the interpreter lock so I can avoid calling PyEval_AcquireLock again? If so, is it available all the way back to 1.5.2? -- Robin Dunn Software Craftsman robin@AllDunn.com Java give you jitters? http://wxPython.org Relax with wxPython!
Is there an easy way in the API to check if the current thread already has the interpreter lock so I can avoid calling PyEval_AcquireLock again? If so, is it available all the way back to 1.5.2?
I don't think so. It's easy to check whether *some* thread has the lock, but the lock abstraction doesn't have a notion of ownership by a specific thread. Let's take a step back. Why do you need this? I'm guessing that you have a C++ library that calls C++ callbacks, and now you want to call a Python callback from your C++ callback. The proper solution is to make sure that you *always* release the Python lock before entering your event loop or anything else that could possibly call callbacks. See _tkinter for how I handled it there. It's ugly, but possible. --Guido van Rossum (home page: http://www.python.org/~guido/)
Let's take a step back. Why do you need this? I'm guessing that you have a C++ library that calls C++ callbacks, and now you want to call a Python callback from your C++ callback. The proper solution is to make sure that you *always* release the Python lock before entering your event loop or anything else that could possibly call callbacks. See _tkinter for how I handled it there. It's ugly, but possible.
Yep, I've already got it working this way except there are a few code paths that result in a callback sometimes being called indirectly from a different part of the code where the Python lock is already acquired. I was hoping to be able to use a general solution instead of having to find all those situations and special-case them. Oh well. Thanks anyway. -- Robin Dunn Software Craftsman robin@AllDunn.com Java give you jitters? http://wxPython.org Relax with wxPython!
Let's take a step back. Why do you need this? I'm guessing that you have a C++ library that calls C++ callbacks, and now you want to call a Python callback from your C++ callback. The proper solution is to make sure that you *always* release the Python lock before entering your event loop or anything else that could possibly call callbacks. See _tkinter for how I handled it there. It's ugly, but possible.
Yep, I've already got it working this way except there are a few code paths that result in a callback sometimes being called indirectly from a different part of the code where the Python lock is already acquired. I was hoping to be able to use a general solution instead of having to find all those situations and special-case them. Oh well.
I guess you could have your own global variable that says "I've already got the Python lock". The lock sequences would look like this: // before entering the event loop clear the flag unlock the GIL // after returning from the event loop lock the GIL set the flag --Guido van Rossum (home page: http://www.python.org/~guido/)
Robin, you may also profit from looking at Mark Hammond's utility classes in the win32all extensions, and exploiting platform TLS (thread-local storage) can make it easy to give each thread a "do I own the lock?" flag -- but you need to establish choke points in your own code, i.e. a protocol of your own for dealing with threads, wrapping the raw Python C API.
I was hoping to be able to use a general solution instead of having to find all those situations and special-case them. Oh well.
You can, but the general solution has to come from you now. Callbacks in the presence of threads are a bitch, and redesigning this part of the Python C API is something the thread-SIG intended to tackle but didn't accomplish.
participants (3)
-
Guido van Rossum -
Robin Dunn -
Tim Peters