No, it's actually not going stale. It's kind of weird to describe without getting into the nitty gritty of this particular toolkit. The issue is that the semaphore reference is accessed by two different actors (going outside the Messaging paradigm).
The semaphore reference is linked to a specific subpanel. Each actor creates an object (part of the toolkit) called a "Panel", which has methods you can invoke to show and hide it. When you create the Panel object, you give it a Subpanel reference. Internally, the toolkit generates a named semaphore for each Panel object that gets created. Each Panel gets its own Semaphore reference, but they each point to the *same* Semaphore, they just have unique lifetimes.
To use these Panel objects, you call "Show" or "Hide" methods on the Panel object. The panel object then checks against a FGV "register" to see if it's currently inside of the subpanel. If it isn't, it unloads whatever is in there, then loads itself. It's very handy and it isolates the Subpanel reference, which is nice. The issue is that when it checks to see if it's the current owner of the Subpanel, it returns the Panel object belonging to the current owner, and the *inserting* actor hides whatever is currently in the Subpanel. It SHOULD send a message to the actor in there to do it, instead of operating on there itself, but alas it doesn't.
The issue is that Actor A is acting on Actor B's Panel object at the same time. Actor A is trying to Close the panel while Actor B is trying to Hide the panel. Normally, semaphores prevent both of them from actually *acting* on the Subpanel at any given time- however, in this case, Actor A removes itself and releases the Semaphore reference. In the incredibly short window between when Actor A gives up the lock and when it releases the reference, Actor B grabs the lock. Actor A then releases the reference (that Actor B is currently using), so when Actor B tries to return the lock to the semaphore, it finds that reference invalid.
The thing is, the Semaphore itself (not the specific reference to the semaphore, but the actual named semaphore) never dies through this process, so from the semaphore's point of view, the Lock is taken but never returned.
In short, the semaphore isn't going stale, but the reference is being released while something else still has that particular reference.
Hope that helps. Thanks for the ideas on how to fix things. Unfortunately the Semaphore work is all being done in non-AF code parts, so I'd have to do some heavy refactoring to make it fully AF compatible, which would then break the non-AF implementations (which I also use elsewhere).
The solution I posted above seems to work for now; I'm able to release the specific shared reference, meaning nothing else can grab it, and return the Lock to the Semaphore pool via another temporary reference generated and released in the same Close VI.
Uh oh. I used a Semaphore in a recent project, and looking at it I think I have the same potential issue, due to the inability to, atomically, both release a lock on a Semaphore and also release the reference to the Semaphore. Parallel code trying to lock-then-release the same Semaphore reference will wind up leaving the Semaphore forever locked.
Yep. If it's a named semaphore you can create a new temporary reference which you can use to unlock it; if it's an unnamed semaphore I don't know if you can do that or not.
I threw the concept up on the Idea Exchange here:
I'd love to hear more thoughts on how to combat this issue.
So here's the full story.
The MGI Panel manager framework's goal is to do all of this fancy stuff without the developer having to do anything. It should handle weird situations that a novice developer didn't even know existed.
One of these weird situations comes when two processes need to access the same subpanel. The panel manager framework lets each process decide when it's time to put "Me" in the subpanel. This means that it's very possible for one process to be removing something from a subpanel while another is adding to it. There are a whole bunch of race conditions that can happen.
To avoid these race conditions I needed a lock. So while one process is messing with the subpanel the first thing it'll do is acquire the lock, then perform it's actions, then release the lock. So I used a semaphore.
The problem is I create the semaphore ref once, and used it all over the place. This means that it's possible for one process to release the semaphore ref while another was still using it. This would cause the deadlock that Bert found.
Here's the thing about the semaphore ref though: I really don't need it to be valid all of the time. All I care about is right now, is anyone else messing with the subpanel?
So that means I can just create a new semaphore ref right before I need it, then acquire the lock, do what I need to do, then unlock it and release the reference. This means that each process will have it's own reference to the same semaphore, and nobody will be accidentally stomping on the stuff that another process is working on.
Mega thanks to Bert for tracking down this bug. He did all the hard work.
Side note: Panel manager should be showing up on the tools network any day now! I'll get this latest fix posted as soon as possible.
In searching for "MGI Panel Manager race condition" I came across this post. This is very interesting stuff about the semaphore usage. I am not using Actor Framework, so I do not believe I would suffer from this issue. (And my toolkit may be of a newer version.)
I have also found a race condition within the Window Position:Persistent Position class, and have posted the issue separately here:
I thought it might interest folks using the Panel Manager toolkit that may see this issue as well.
For what it's worth, once I figured out the issue I sent an email to Derek at MGI (his contact info should be on their website or in the Help files for some of the Panel Manager stuff, as he wrote it).
He understood the issue immediately and was able to come up with a solution and patch it quite quickly, and was super helpful. I'd shoot him an email and let them know what you found.
I had the same idea. However, when I went to MGI's Contact page, there is no more Derek. His NI Forums account seems to be active, so I'm sure he'll see this eventually. Not sure of the best contact at MGI for this.