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 have 'barebones' singleton and cloneable module templates that I always use when creating new DQMH modules for projects. I started with the shipping module templates and removed:
- 'Do Something' events
- All #Bookmarks
- Simulate EHL/MHL error buttons
I propose DQMH ship with these simple module templates. They help save several minutes when creating a new module. I'm not suggesting changing the project template, but rather simply adding two new options in the Add New DQMH Module drop-down:
Most of the time we create multi-layer applications, and bottom modules need to share information that might have to cross several upper layers.
To avoid coupling and jumps between any non-adjacent layers, we have to create similar broadcast in the parent modules to repeat child broadcast one layer upper.
It would be interesting to have a utility that 'copies' an existing broadcast from one module into another.
And maybe have an option to code the forwarding :
automatically register for child broadcast in the parent if not done already
in the selected braodcast EHL case, map broadcast arguments onto parent broadcast VI inputs
I guess the same thing can be done when the communication needs to go down the layers, and therfore applied to requests.
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)”.)
Wouldn't it be great if double-clicking on certain failures in the Validator results window took us directly to the related place on the BD or the corresponding VI in the project window?
I'm thinking about the ones where you need to manually do something. Like disconnecting the Main VI terminals from its connector when moving from Run VI method to Start Async method, or updating your static VI ref by dragging the main VI onto the constant...
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 😉
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 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.
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.
Lately I've been running into lots of code that looks like this:
I just need to start a module, call a request (and wait for reply, usually), then stop the module. I think it would be convenient if the module templates included a 'Start and Sync Module' VI that wrapped the Start Module.vi and Synchronize Module Events.vi. This is for the use case where you won't be needing to register for any of the module's broadcasts.
In order to reduce the number of clicks to launch a DQMH scripter, that would be great to be able to launch them from the LabVIEW New... menu !
Indeed this window has several advantages :
The tree view keeps its layout from one excution to another. So if the last thing I did from that window was to launch the 'New Event...' scripter, next time I'll launch this window this item will be directly accessible
It allows inserting the created code into the project or not. So to create quick code without adding it to the currently open project, this is quite usefull
The tree view makes easier to choose the scripter to launch. With Tools menu, if the mouse pointer accidently leaves the menu and overs another menu entry, you've got to go back and re-do some of the menu selection process
A LV keyboard shortcut can be added to the New... action. In my case I redirected the CTRL+N shortcut to launch the 'New...' window instead of triggering the 'New VI' action. It would allow me to launch a scripter with 1 keyboard shortcut + 1 double click ! Quite fast !
A round-trip can be summarized as a Request and Reply event + broadcast of the reply.
Round-trips are particularly useful when debugging systems where the access to the module itself is hard to get (like when using TestStand / VeriStand platforms). They are very good sniffers to understand what's going on under the hood.
I would find it very valuable if the broadcast could also carry the request arguments !
This way the 'sniffer' could expose the context of the reply : reply is formed that way when the request contains such arguments.
It can be hard to follow the flow of messages between DQMH module in a large project.
I find sequence diagrams great to document that, one tool that would rock is something that looks like a UML Sequence Diagram that is updated as messages are being sent. Columns generated the first time a module is started and then the lifelines of the modules are generated and terminated in their column.
When NI released VI Analyzer 2018, they included a feature to ignore VI Analyzer test failures for specific objects and VIs through the use of #via_ignore bookmarks:
I would like similar functionality for ignoring DQMH Validate Module failures. I propose that if a VI contains a #dqmh_validate_ignore bookmark anywhere on its diagram, then that VI will not return a failure for any DQMH Validate Module test whose name is included in that bookmark's label. Something like this:
Some of my events have a common events arguments and/or reply payload. Creating a template would speed up their creation.
Also, when using round trips from TestStand, I made a modification to the content of a round trip event to easily handle termination. It could be nice if this modification could be saved as a template, so that every round trips I create to be used within a TS sequence would contain automatically that modification.