09-11-2018 05:51 AM
I'm working on a larger application with plug-in architecture, where some plugins write to DB, some read and outputs, and some read and displays.
LabVIEW 16.0f5 32-bit. The type of database is 5.5.45 MySQL running locally.
If I'm running multiple "Read" plug-ins the program will crash after a short time (5min - 30min).
According to the crash report this happens in "Recordset.llb\\Rec Fetch Recordset Data (R).vi" (see attached).
If there is only one "Read" plug-in running the program will run for days, and maybe never crash.
I will add several Read processes to stress test.
I'm getting the impression that the crash happens when two processes reads from the DB at the same time.
Each process opens a connection to the DB. I've been thinking about implementing a locking mechanism, but it's a little complicated to do.
Could this be related to the cursor type? I tried changing it to "static", to see if it made a difference, but it doesn't seem like it mattered.
Sounds familiar to anyone? How can I debug this, is it LabVIEW or the database, is it the Database API or my code.
Thank you for reading!
Solved! Go to Solution.
09-11-2018 07:12 AM
@Oksavik wrote:
I've been thinking about implementing a locking mechanism, but it's a little complicated to do.
Poor man's synchronization: use a VI. If the VI is not reentrant, each run will wait for the VI to stop running. Instant locking mechanism. Not complicated.
09-11-2018 07:18 AM
Hello, and thank you for your reply.
As far as I can tell the NI Database API VIs are already not reentrant. However, I'm afraid that the plugins are including some of these VIs through dependencies in their packed libs.
If this is the case I suppose they could be executed simultaneously, even though they are not reentrant.
I'm trying the locking mechanism now, however will a semaphore work "across" different packed libs?
09-11-2018 07:19 AM
@Oksavik wrote:
I've been thinking about implementing a locking mechanism, but it's a little complicated to do.
Poor man's locking mechanism: use a VI.
If the VI is not reentrant, each run will wait for the VI to stop running. Instant locking mechanism. Doesn't need to be complicated (but could be).
@Oksavik wrote:
Could this be related to the cursor type? I tried changing it to "static", to see if it made a difference, but it doesn't seem like it mattered.
What cursor? What do you mean by 'changing it to "static"'. If you suspect the cursor, disable all code that changes the cursor. Setting it to static could still make it crash.
Are you 100% sure you close all connections\references? There could be a limit to how many references (of some kinds) are allowed to be open. If they are not all closed properly, you might run out.
@Oksavik wrote:
Sounds familiar to anyone? How can I debug this, is it LabVIEW or the database, is it the Database API or my code.
Desktop Execution Trace Toolkit maybe?
Try speeding up certain things to see it crashes occur more often. Or slow down things. Or disable parts.
If concurrency problems are suspected, make a test VI that queries the DB, and start it in parallel with some randomness. E.g. try to force crashes.
09-11-2018 07:22 AM
Sorry, that post crashed, although it got send anyway...
09-11-2018 07:27 AM
About "cursor type". One can select from 4 different cursor types when working with RecordSet in the Database API.
For some reason I had a thought that this might be related to the crash, but it can be completely unrelated.
The default type is "ForwardOnly" which according to the link under is the most limited.
http://download.nust.na/pub6/mysql/tech-resources/articles/vb-cursors-and-locks.html
References are closed. Also I have had the crash within the first second of running the program, and after 15 minutes. Seems very random.
Speeding up Read frequency / adding more Read functions seems to make it crash quicker.
I tried running two VIs that query the database continuously at the same time, and I did not get a crash.
09-11-2018 08:16 AM
Sounds a bit like you need to isolate exactly what is causing the crash.
A bit clutching at straws as these shouldn't cause crashes but:
Prehaps try updating the ODBC driver?
Are you ensuring that the DB references are held in shift registers through any loops?
09-11-2018 10:15 AM
You need to package your DB code into its own PPL that the other components will use. Otherwise each PPL will load its own copy of the DB code a which is most likely what is causing your crash.
While PPLs are a great tool they can complicate your life. Once you start using them you need have to fully commit since if you are using re-use libraries. PPLs will load their own copy of a library or set of VIs. Best case this just means that your application is using more memory. Wort case you get conflict, especially if any of your libraries need to maintain state since you end up with multiple copies. We switched to using PPLs about a year ago and we are now approaching 150 of them to make all of our reuse libraries work properly.
09-13-2018 06:54 AM
This was my solution. It required some heavy refactoring, but the result is much cleaner code, and best of all: so far no crashes.
My situation was that my DB code (a lvlib built on top of NI Database API) was used in multiple of the PPL.
Each PPL made a copy of the code, which was not made to be run re-entrant. When the PPLs started making calls at the same time it would crash.
One of my issues with PPL has been that PPLs that inherit from another PPL would be time consuming to work with.
If I needed to make a change in the parent PPL it meant manually reverting inheritance for all the children.
I feared that this would get much worse if I compiled my DB code into a PPL, and replaced the lvlib with lvlibp for all the children PPLs.
I realized that having separate LV-projects for the DB code PPL would be a good idea. So I broke my two projects into four, and now things are much easier.
Make changes and build DB code PPL. Import this in "Top plugin"-project, and build Parent plugin PPLs. Import them into "Actual plugins"-project, and build Child plugin PPLs. Import these in Main-project, where I create an .exe file. In the end the application was half the size (18 Mb -> 9 Mb).
Hope this might be helpful for someone else later.
Thanks Mark_Yedinak.
09-13-2018 07:47 AM
Are you using "inherit", "parent" and "child" as in OO relations?
Or do you mean "inherit->uses", "parent->using", "child->being used"?
As in:
"One of my issues with PPL has been that PPLs that inherit from another PPL "
-> "One of my issues with PPL has been that PPLs that is using another PPL "
", and replaced the lvlib with lvlibp for all the children PPLs."
->", and replaced the lvlib with lvlibp for all the PPLs that are used."
etc.