views:

117

answers:

1

This is a difficult problem to describe so please let me know if anything is unclear.

I am trying to solve a possible deadlock situation in my C++ app and I am having trouble visualizing an appropriate solution. The restrictions placed on me by the two libraries I am trying to connect make my problem very complex and troublesome but it can all boil down to a simple diagram. Quite simply I have a situation like so

Python    |                 Thread 1                  Thread 2
          |
Action 1 -|-> GIL LOCK -->  Random Calls
Action 2  |   GIL LOCK <----------------------------- [Action 2]
          |                 Action 1 -- signals --->  Do_Action_1
          |                 Wait Forever              Wait on Action 2

Action 2 happens to be a timer firing, the library I am using has this timer code that will call functions after a set amount of time.

Trouble occurs when a timer fires while I am destroying the timer handler (Action 1). The timer handler will wait for the timers to finish their functions and the timer functions cannot finish because they are waiting to call a python function. In order to get into python they need to take the GIL which is being held by the timer handler destruction action.

I am wondering if its possible for me from Thread 1 to interrupt its wait on the GIL and unwind its stack to put it out of harms way of this deadlock. Although I fear going down to far into specific OS implementations I just can not think of any better solution.

In other words, I want to cancel the Action 2 call from thread 1. Is this in ANY way possible?

I should mention that I cannot edit the operation in Thread 2 ie, I cannot edit that library that is managing that thread. I can modify python's GIL lock to maybe be a try lock or a timed lock or maybe even a wait on a condition but that would be really hard to pull off.

I suppose the best solution would be to modify python to wait on the gil and a named condition that my Thread 1 can signal when I want to cancel its wait on the GIL. But before going down that route I want to know if I am missing anything.

A: 

If you're destroying the timer handler, I figure you're exiting the program. Before you try to exit and begin killing the timers, can you set a flag to prevent Action 1 and have Thread 1 terminate itself? I hope I'm reading your diagram right, because it doesn't exactly match with the text...

Mike D.
The problem is that as soon as I cross from python into my C++ code the while thing is vulnerable to this. So for this to work I would need to set the 'do not allow action 2 to try to lock the gil' flag the moment python calls into my C++ app.I tried setting a flag in my program to prevent the call handler from locking the GIL but all I managed to do was make the deadlock window a little smaller.btw Action 1 is the timer destruction
Charles
Unless you have some way to stop all timers before destroying anything, I think you're stuck and may need to take a whole different approach. You say you're trying to bridge two libraries. I'm assuming they're both C++ libraries. You may have to add a third thread which acts as a proxy for Python, and is the only thread allowed to mess with the GIL. In other words, handle things like multithreaded apps handle most GUIs: Restrict all GUI work to one thread and have the others proxy through. I can't really recommend more without a better idea of what your tasks really are.
Mike D.
that is one route I might end up taking, although I do not like the idea and it would be very prone to problems :(I did find this question on a related search http://stackoverflow.com/questions/2135457/how-to-write-a-wrapper-over-functions-and-member-functions-that-executes-some-cod which indicates that its ok to release the gil once you are in the Cpp world as long as you take it back when you go back, so I have been investigating this approach. thanks
Charles