LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Event Case Structures: Race Condition?

Hi all,

I'm trying to debug a certain issue. Attached is an extremely rudimentary sketch of the set-up. It also doesn't demonstrate the problem I'm having but it's just to give a rough idea of the set-up

 

One loop is a state machine, where a bunch of code collects some values.

These values are written at a slower rate to a text file (represented by the subvi) in a separate loop. An event case structure is used so that values are continually recorded in the timeout case and are not of significance but has to be recorded anyway and a type def enum defines the values as unimportant or as critical points as defined by the user by pressing a button or defined by the program using certain parameters (the latter is not reproduced in the attached example)

 

The problem that has cropped up is that for the most part it works as intended but occasionally the last "critical point" values has the label of "Ignore" instead of whatever case it's defined as.

 

At first I thought it might be a race condition, that the critical point event never fires, but I believe a Value Signaling event should always fire and even if the code takes longer to execute for whatever reason, it should still complete the event case due to the checkmark on the lock panel before the event handling loop is stopped

My second thought is that despite changing the value of the local variable for the typedef control BEFORE the event fires, the local variable does not actually update in the event case. Is this something that is possible?

Thirdly, is it possible that the case structure in the subvi executes the default case because it's just reading the default value of the control and ignoring the input. What happens if I remove the default case setting if every case is defined anyway?  

 

Thank you in advance!

0 Kudos
Message 1 of 10
(1,336 Views)

Hello nikvl,

Make sure you follow proper state machine architecture and avoids using Sequence Structure.

 

Most of your case properly wiring the error cluster will sequence your code without using the Flat Sequence.

----------------------------------------------------------------------------------------------------------------
Palanivel Thiruvenkadam | பழனிவேல் திருவெங்கடம்
LabVIEW™ Champion |Certified LabVIEW™ Architect |Certified TestStand Developer

Kidlin's Law -If you can write the problem down clearly then the matter is half solved.
-----------------------------------------------------------------------------------------------------------------
0 Kudos
Message 2 of 10
(1,322 Views)

Hi Palanivel, yes thank you. I usually try to avoid Sequence Structures and this was just a quick mock up.

0 Kudos
Message 3 of 10
(1,311 Views)

Hello nikvl,

 

Before answering your question about the race conditions, I have a few general questions and comments about this code:

1. Are you sure this simplified code represents accurately enough the application code that exhibits the issue? For example, is the recording code doing things like checking for duplicate "Values" entries before recording it in the file?

2. In my opinion, using local variables for "Values" and "Case" between these two loops is tricky and may be prone to race conditions. It would make more sense to generate a User Event from the State Machine loop to be able to send commands losslessly. You could include parameters, i.e. "Values" and "Case in your case. This would guarantee that a Critical Point is applied with the correct Values and Case.

3. Using the Timeout case in the Event structure can also be tricky in some situations, because it may not trigger depending on how many events the Event structure receives per unit of time. This occurs if you use Value Signaling and User Events. I have seen issues with Timeout cases in various applications because those cases stopped triggering when changing a seemingly unrelated part of the code by adding or increasing the frequency of Value Signaling or User Event generation.

4. I think that this bug can likely be debugged using probes and the Event Inspector Window (see View menu) in the code of your actual application, if it occurs often enough to be able to reproduce the bug.

 

To come back to the race conditions of this simplified code, which does not exhibit the buggy behaviour (at least not with the same probability), I don't see any reason for the last Critical point to not be recorded. As mentioned in my point 1 above, however, if there is some kind of ignoring of duplicate values in the recording SubVI in the real application, then I can imagine the following scenario happening:

a. In the State Machine's State 2, "Values" is updated with the final value, because "Stop Loop 2" is True. The loop must wait 100ms, due to the Wait function.

b. In parallel, the Event loop's Timeout case is triggered, reading "Values" and using "Case 1", recording the values to the file with the "Ignored" text.

c. In the State Machine's State 2, "Values" is updated again with exactly the same final value as in point a and "Case" is also updated. Then the Critical Point event is sent.

d. The Event loop's Critical Point event is triggered, reading the "Values" and "Case" via local variables. The SubVI ignores this point because "Values" are already in the file.

0 Kudos
Message 4 of 10
(1,304 Views)

Can you explain exactly how you run this, what controls you press an in what order and where we are supposed to look for unusual results.

 

Also indicate what we should not do, e.g. press stop2 before stop1, etc.

 

Can't really start debugging before that. Too many branches...

 

I also strongly recommend to eliminate all these stray init to default nodes. There are better ways!

 

This entire architecture is a "tail wagging the dog" kind of thing with a UI loop with inner loops, triggering events via indicators and their signaling events. There are also way too many sequence structures.

My gut feeling is that this should be arcitected in a more conventional way.

0 Kudos
Message 5 of 10
(1,273 Views)

@gsafar wrote:

Hello nikvl,

 

Before answering your question about the race conditions, I have a few general questions and comments about this code:

1. Are you sure this simplified code represents accurately enough the application code that exhibits the issue? For example, is the recording code doing things like checking for duplicate "Values" entries before recording it in the file?

2. In my opinion, using local variables for "Values" and "Case" between these two loops is tricky and may be prone to race conditions. It would make more sense to generate a User Event from the State Machine loop to be able to send commands losslessly. You could include parameters, i.e. "Values" and "Case in your case. This would guarantee that a Critical Point is applied with the correct Values and Case.

3. Using the Timeout case in the Event structure can also be tricky in some situations, because it may not trigger depending on how many events the Event structure receives per unit of time. This occurs if you use Value Signaling and User Events. I have seen issues with Timeout cases in various applications because those cases stopped triggering when changing a seemingly unrelated part of the code by adding or increasing the frequency of Value Signaling or User Event generation.

4. I think that this bug can likely be debugged using probes and the Event Inspector Window (see View menu) in the code of your actual application, if it occurs often enough to be able to reproduce the bug.

 

To come back to the race conditions of this simplified code, which does not exhibit the buggy behaviour (at least not with the same probability), I don't see any reason for the last Critical point to not be recorded. As mentioned in my point 1 above, however, if there is some kind of ignoring of duplicate values in the recording SubVI in the real application, then I can imagine the following scenario happening:

a. In the State Machine's State 2, "Values" is updated with the final value, because "Stop Loop 2" is True. The loop must wait 100ms, due to the Wait function.

b. In parallel, the Event loop's Timeout case is triggered, reading "Values" and using "Case 1", recording the values to the file with the "Ignored" text.

c. In the State Machine's State 2, "Values" is updated again with exactly the same final value as in point a and "Case" is also updated. Then the Critical Point event is sent.

d. The Event loop's Critical Point event is triggered, reading the "Values" and "Case" via local variables. The SubVI ignores this point because "Values" are already in the file.


Hi, first of all, thank you for considering my problem. To answer your questions:

1. Actually this "main vi" is also a subvi that is called into a subpanel on the top level panel. (So the subvi here is a subvi within a subvi). The original code is quite complex and I tried as best as I could but it's not a 100% guarantee I didn't miss anything. The recording code does keep checking if the file exists and if not it should create a new file. It does not check for duplicate values however.

2. I have a Generate User Event for a panel close event in the top level vi. Is okay to have multiple Register for Events/Generate user event in different subvi? I don't want to change the architecture that drastically as that might crash it.

3. Yes, but there are long enough periods where there is no user activity so timeout will definitely execute. What do you mean that by increasing the frequency of Value Signaling that the cases stop triggering?

 

Regarding your proposed scenario:

d. wouldn't the subvi just read the values twice even if it's a race condition? The value change trigger is on the event critical point boolean and not the values themselves? In any case in my data the values are not duplicated but it is the case assigned to it that stays on "Ignore". So I feel either the event is not generated at all, or it is generated with the latest values but case structure does not.

0 Kudos
Message 6 of 10
(1,264 Views)

@altenbach wrote:

Can you explain exactly how you run this, what controls you press an in what order and where we are supposed to look for unusual results.

 

Also indicate what we should not do, e.g. press stop2 before stop1, etc.

 

Can't really start debugging before that. Too many branches...

 

I also strongly recommend to eliminate all these stray init to default nodes. There are better ways!

 

This entire architecture is a "tail wagging the dog" kind of thing with a UI loop with inner loops, triggering events via indicators and their signaling events. There are also way too many sequence structures.

My gut feeling is that this should be arcitected in a more conventional way.


Ah sorry. First press Stop loop 1, and then Stop loop 2 in that order, and not the other way around. The Stop loops represent a few conditions really, either a condition is checked and the loop is stopped, the user decides to cancel the process, etc. State 1 needs to run, the collected values are not important to the user but needs to be recorded anyway. In State 2 some values might be important at some point in time (i know the while loop contents look similar to state 1 and it is in the sense they are in generating values but there are other things in the code that distinguish it from state 1) and that's when stop loop 2 is triggered.

 

Yes the architecture needs to be better but it's too late at this point, and the sequence structures was a quick and dirty way to show the set up.

0 Kudos
Message 7 of 10
(1,255 Views)

Check whether this Modified Main Loop structure supports your logic.

----------------------------------------------------------------------------------------------------------------
Palanivel Thiruvenkadam | பழனிவேல் திருவெங்கடம்
LabVIEW™ Champion |Certified LabVIEW™ Architect |Certified TestStand Developer

Kidlin's Law -If you can write the problem down clearly then the matter is half solved.
-----------------------------------------------------------------------------------------------------------------
0 Kudos
Message 8 of 10
(1,222 Views)

Overall, if the recording SubVI does not check for duplicate values, then I do not know why your code writes the wrong label for the last (critical point) to the file.

Here are my answers:

2. You can register multiple User Events for a single Case Structure without issues.

3. Regarding the Timeout, what I meant is that if the loop receives events too often, then the Timeout case could be triggering more slowly or not at all, anymore. Glad that this isn't the case for you!

d. If there is no checking of duplicate values (as you mentioned), then the value would show up twice: once with the "Ignore" case and once with the case read from the local variable "Case".

 

Can you show the code where you record the Values + Case to the file? Maybe there is a bug there?

 

0 Kudos
Message 9 of 10
(1,212 Views)

. I have a Generate User Event for a panel close event in the top level vi. Is okay to have multiple Register for Events/Generate user event in different subvi? I don't want to change the architecture that drastically as that might crash it.

 

Oh magic 8-Ball ~~~~~

Are ANY of the Event Structures that are looking for the Dynamic Event fired by Main.vi Panel Close(?) force destroying the Event Registration?~~~

Almost certainly 

 

MULTIPLE Event Structures can be registered for the same Event.   There are caveats clearly addressed in the Help file for doing that correctly.   The Event itself must first complete on each structure prior to being passed on to the next Event Structure (or, potentially discarded in the case of Filter Events.)  The order of the sequence that the Event Structures operate is by whichever Event Structure registered for the Event First.  Thankfully,  the Event Inspector Window will help debug the order now (it used to be a total shell-game.)

 

What you are describing sounds like you have registered for a dynamic Event that cannot be fired because the Event itself is Closed before the Event Structure where the Event is registered has had the Event passed to it.  Nasty problem!  And YES! That is how you can get a classic Race Condition with Events. 


"Should be" isn't "Is" -Jay
Message 10 of 10
(1,192 Views)