From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

MGI Panel Actor hanging?

Solved!
Go to solution

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.

0 Kudos
Message 11 of 17
(1,541 Views)

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.

0 Kudos
Message 12 of 17
(1,537 Views)

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:

 

https://forums.ni.com/t5/LabVIEW-Idea-Exchange/New-function-Atomic-semaphore-unlock-with-reference-r...

 

I'd love to hear more thoughts on how to combat this issue.

0 Kudos
Message 13 of 17
(1,535 Views)
Solution
Accepted by topic author BertMcMahan

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.

 

The Fix:

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.

Message 14 of 17
(1,490 Views)

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:

https://forums.ni.com/t5/LabVIEW/MGI-Panel-Manager-Persistent-Window-Position-Race-Condition/td-p/40...

 

I thought it might interest folks using the Panel Manager toolkit that may see this issue as well.

_______________________________________________________________
"Computers are useless. They can only give you answers." - Pablo Picasso
0 Kudos
Message 15 of 17
(1,069 Views)

Good info.

 

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.

0 Kudos
Message 16 of 17
(1,064 Views)

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.

_______________________________________________________________
"Computers are useless. They can only give you answers." - Pablo Picasso
0 Kudos
Message 17 of 17
(1,059 Views)