We have identified that, if multiple clonable module instances are executed and a specific module (e.g. the first launched module) is stopped (no waiting) and afterward all open modules are stopped at once (incl. wait) the "stop module.vi" an error 1 is returning.
Steps to reproduce
Create a project and add a new clonable module
Create a tester VI and implement the code above
Run the VI and see error 1 at second Stop Module.
What is happening in the Background
Situation 1 - "Stall Data Flow" = 0
"Stop Module.vi" 2 runs into "Wait on Stop Sync.vi" and synchronizes stop over rendezvous. The acquired rendezvous size is 3 (Module 1 which is at stopping, Module 2 and Stop Module)
Module 1 is waiting in "Safe to Destroy Refnums.vi"
Module 2 runs into "Close Module.vi"
Last clone instance is fire at (1)
Releasing the Semaphore (2) will wake up module 1 that it is now safe to destroy refnums now. Module 2 runs into "Wait on Stop Sync.vi" (3) and synchronizes over rendezvous.
"Stop Module.vi" and Module 2 waiting for a third participation to join the rendezvous.
Module executes case to destroy Master reference.... and executes "Wait on Stop Sync.vi" (3) with no synchronization as the boolean "Wait for Module to stop?" is on false.
Module 1 executes "Destroy Sync Refnums.vi" (4) and is destroying the rendezvous.
Module 2 and "Stop Module.vi" will be release from the waiting of the rendezvous as the reference is now invalid and returning error 1.
Situation 2 - "Stall Data Flow" = e.g. 2000ms
In compare to the situation 1 the first module is already removed here. The obtained rendezvous has the expected size of 2.
When module 2 enters rendezvous synchronization in "Wait on Stop Sync.vi" (3) the expected amount of participant is reached, and the execution can continue.
In most of our tests, this situation worked fine and did not create an error.
For some situation, we had the behavior that shutdown of the first module seems to be faster as the wake-up from rendezvous of the second module. The module main of module 2 opened and showed error 1. Module 1 seems to destroy the references to early.
Situation 3 - First Module will be stopped with last "Stop Module.vi" call
The shutdown of a module is for this scenario delayed (add a wait 1000ms to exit case of the module)
Stop Module 2 waits for 11 rendezvous participations. (10 module and itself)
One of the previously closed module will destroy the synchronization events and makes the rendezvous reference invalid. => Error 1 at "Stop Module.vi"
The following screenshots are showing an extension of the "Stop Module.vi" and the "Close Module.vi".
The idea is to use a single element queue (SEQ) containing a map of sets. The key of the map refers to a "Stop Module.vi" which waits for stopping all module at the time when the "Stop Module.vi" is executed. The Set contains all Module ID's which should be stopped. Each module checks in its close condition if the SEQ is existing. If so, the module ID will be removed from the sets which containing the module ID. An empty set refers to all required modules have stopped and a notifier which is used for synchronization will be fired. Close Module.vi extention Stop Module.vi extention
With those extensions, all three described scenarios should be fixed. In addition, should it be possible to stop all module and launch in the background new ones, the stop and wait will wait until all those modules ID run at the stop execution are finished.
I added the project which the extensions and tests to the post.
Addition
I'm not sure, but I think that with the described change, destroy of the Module's Semaphore (1) should be done with the boolean condition of the First & Last Instance (2). (Red line)
Please let me know if you need any additional information and details.
I dislike using Clone IDs, Whenever I have used Clones in real life application, I always start by editing the Start Module VI and adding in a Clone name input. As I do this for all my clones the input name tends to be specific like 'Bay Name', or 'PSU Name' but a generic 'Clone Name' would be good.
I then pass that Clone Name into my MHL Data cluster in 'Initialize', each clone now knows it own name this allows things like
A Request to all Clones to get the instance for a name, so calling code can work in terms of Set Voltage(UUT_PSU), Set Voltage(RIG_PSU) rather than Set Voltage(45568) Set Voltage(40056), making a clone manager more code easier to read. -- I know this could be done in a clone manger with a Map or table, but I like the idea of the Clone know its own name.
As the clone knows it own name, because I gave it its name, this means clone instance configuration is easier, I have can have a single configuration ini file with each clone name as separate sections or I can have each clone read from its own ini file simple based on its own name.
Modules other than the clone manager can if needed talk to the correct clone using the name they do not need to know about the instance.
Thinking about this it would be, to my mind, a great feature addition to DQMH is by default there was a optional for providing a clone name at startup that was accessible as a Mod Admin property alongside the Module ID.
As mentioned in DQMH Forum: VI Reentrance issue VIs which are required to be non-reentrant are not reported from the DQMH validation tool if they were changed (e.g. to shared clone)
Some of the important VIs which should be reported:
Currently the DQMH stock requests / broadcasts (eg: Stop module, Hide panel etc) are mixed with the user created requests / broadcasts so if one likes to check which requests, broadcasts etc are in the module he needs to open different subfolders and visually filter out the stock events.
This is a readability issue which makes it significantly harder to quickly understand (or recall) what events are available for the given module.
Possible solution:
Instead of mixing the stock DQMH events with the non-stock events create a virtual folder above all the virtual folders called "Module Specific" with subfolders like Requests, Broadcasts, Private and Controls and put everything the user create to there by default.
Big advantage of this of organizing the files this way would be that one could assume that whatever is module specific can be found in the these dedicated folders instead of spreaded somewhat randomly in the virtual folder structure of the module. I said somewhat randomly because the strucure as is currently is hard to read so developers try to make it more readable, everyone on his own way (eg: creating different folders, prefixing the user created events etc). So besides the increased readability of the module by applying this feature there is a very good chance that modules' structure will become more standardized across developers working at different companies.
Open the block diagram and find the event frame configured for this request (It might no longer be listed and instead say something like “Unknown Event (0x0)”).
Open the block diagram and find the event frame configured for this broadcast. (It might no longer be listed and instead say something like “Unknown Event (0x0)”.)
When validating a number of modules and going through the list of fixes, it's sometimes hard to keep track of what has already been fixed.
It would be nice to have some information on which failures were already fixed, and whether the fix was applied successfully or if there were errors or if there's a need for manual work.
I just put some icons into the screenshot to illustrate my idea - my feature request asks for a prettier implementation 😉
When you create a Request and Reply event, the scripter creates such code in the MHL :
And I always end up refactoring it this way :
('Status update' related code can be ignored if it is a bit too much). Is it possible, using scripting, to directly script that so we don't have to do this each time ?
We are constantly having deployment errors on RT targets, mentioning the Simple Error Handler. Since on RT Targets that function is useless anyway, we've put a conditional disable structure around. This solved the error.
It would be nice, if that CDS would be added to a standard DQMH module.
There is an option to convert Requests to Request and wait for reply but requests can not be converted to Roundtrip, so a broadcast has to be created manually with payload identical to the Request. Creating a Broadcast is not much of a deal but having two identical payloads is not ideal especially if the payload bundles multiple typedefs.
Find all while loops in the Main.vi of the specified module(s), and check if the DQMH Error Handler - Helper loop.vi is used to handle errors in each of the while loops, and flag it if not. Ignore the default EHL and MHL in this check.
When adding a new event, I think it would be really nice if the scripting code that adds the new case structure case to the main VI also scans the event description for formatting tags, and then applies them to the new case's subdiagram label. That way the subdiagram label will be formatted exactly the same way as it appears in the VI documentation. For those of us who adhere to the convention of bold facing control names as we mention them when writing VI documentation.
I want to be able to try to fix or poke the code more when an error occurs in the API Tester. The opportunity of going to the block diagram or attempting to send a different request goes away because the API Tester, by default, closes when an error occurs.
How I propose fixing it:
The first thing that I change on an API Tester at the first error is to remove the OR connected to the stop terminal in the loop and add an error indicator at the end instead of the Simple Error Handler and connect a local variable for the error. Would you please vote to have DQMH do this by default and have a validator to modify existing API Testers?
Current API Tester:
Proposed change:
Thanks,
Fab (yes, being the DQMH Lead Architect does not guarantee that all my wishes are turned into reality 😉 )
By default, in the MHL Error case, the "error out" local variable is written to. But the error that is written is NOT the error that came into the MHL Error case!
I propose the above be changed to this:
By doing this, the actual error that was raised by the module will be copied to "error out"
JKI State machine has a great tool that comes with it, when you right clic on a BD element of a VI that contains a JKI State Machine, the option menu has the item "JKI State Machine explorer", fantastic tool to facilitate browsing the numerous frames of the case and of the event structure.
A similar tool for the DQMH module would be a great help!
When you update the DQMH version, you can have hundreds of failures to fix in your projects (not because everything is broken but just because, for example, a new feature requires updating a VI).
A fixer is available most of the time, and you just have to click the button to make the code change.
For me, the UX issue is that after you hit the fix button, you need to select the next failure with your mouse and then click on the fix button. I'm not too fond of this kind of mouse gymnastics.
My proposition: If the fix is successful, the next failure could be selected automatically.
The fixing process would be significantly improved.
Running the validator on bigger projects takes quite long.
Would it be possible to speed up the process by running the validation of the modules in parallel?
Additionally: Also in CI/CD we know if the module has changed at all. It would be nice if the cli-module-validation could be called with a .lvlib instead of a .lvproj. Therefore, it could be handy to have a VI which lists all dqmh modules in a .lvproj.
Include a "checkbox" onto the Add New DQMH Module dialog panel that is labelled "Include a Helper Loop"
If the user checks this checkbox, a helper loop is automatically added to the Main.vi
The helper loop would not be a sub-VI, but simply a third loop on the main.vi block diagram.
A Wake up Helper Loop request is automatically created and included in a Private Requests virtual folder
Make the helper loop generic as per Sam's suggestion. My suggestion is to have three user events: 1) Timeout 2) <Stop Module> 3) <Wakeup Helper Loop>
Label the additional "Register for Events" node something different from the other "Register for Events" node, ie. DQMH_REG_EVENTS_HELPER_LOOP (so that the Validate tool does not raise it as an issue)
When generating a helper loop for new cloneable modules, ensure that in the "Wakeup Helper Loop" and "Stop Module" user events, that the Addressed to this Module.vi is used.