Jump to content
Manudelavega

Simultaneous R/W text file

Recommended Posts

So after troubleshooting a complex piece of code for a few hours, I stripped things down to the screenshot below. Apparently writing and reading a text file at the same time causes the read operation to fail. If you force sequential operations by wiring the error cluster from the Read to the Write OR VICE-VERSA, then things work fine.

Does anybody know about this? Obviously my code is way more complicated and the read and write operations are done in different unrelated VIs and in an asynchronous manner. So it seems my only way to fix this is to add a locking mechanism such as a FGV2... However, the file I'm manipulating is actually an INI file and I manipulate it using the native Configuration Data palette, which deep down relies on the R/W Text file VIs. So the FGV2 would need to be added to the native Configuration Data VIs if I wanted to have a generic fix...

The attached VI is saved for LabVIEW 2015.

Capture.PNG

Read-Write TXT issue.vi

Share this post


Link to post
Share on other sites

Since you wired up the file path directly you're performing an implicit open. I would assume that the implicit open uses "read/write" (the default) rather than "read-only" and "write-only" , and opening the same file as writable twice seems like something which labview or windows would take issue with.. Maintaining the reference rather than the path should fix this, as would manually opening the file with the selected access mode.

Edited by smithd

Share this post


Link to post
Share on other sites

Yeah I'd also suggest testing with an explicit open, read write in parallel, and single close.  I'm not certain that the Read/Write will force a blocking call but if this doesn't work then I'd suggest the VIG that you call which forces it to occur serially. 

Share this post


Link to post
Share on other sites

In addition to all the above remarks, your found issue may be anyhow a red herring. The NI INI File VIs read the INI file in the Open Config Data.vi and store its contents internally in a memory list. It is only written back in Close Config Data.vi if the write file if changed (T) boolean is set/left on true AND the ini settings changed in any way by calling actually one of the Write Key.vi methods or the Remove Key.vi or Remove Section.vi.

So collision of read and write to that file only can happen if an open and close can compete simultaneously for control of that file.

The error you see in your simple example is expected behaviour by the way. LabVIEW allows to control the access right and the deny right when opening a file through an explicit File Open node. Your implicit use of the File Open by wiring directly a path to the File Read and File Write opens the file for each operation and for the Write with the deny read and write access. The implicit File Open in the File Read will then bail out with an error as it can't open the file again if the Write managed to grab the file first. In the other case the implicit File Open in the File Write will bail out with an error since it tries to open the file with write access but the File Open in the File Read has opened the file with the deny write specification to prevent inconsistent data during read operations.

Accessing any global resources concurrently requires careful planning and considerations. You either have to allow concurrent access and risk inconsistent data when reading and writing at the same time or you have to handle the sequential access to the file in some way so the read and write won't happen simultanously (and then you could play with the deny and access modes for each to allow the read to open the file anyhow eventhough the write has it open too).

Edited by rolfk

Share this post


Link to post
Share on other sites

What you are witnessing is a race condition specific to the way the implicit write text file works.

I thought it was odd you get an empty string when it fails - the file should never be empty as you would expect to be overwriting the existing data. This VI works though.

My guess is internally the implicitly opened write to text file clears the existing contents first. What you are seeing is a race condition between the file being cleared and the new data being written. I also tried it without the close and that still works (but obviously leaks file handles)

So I don't think this is the root of your problems.

 

read write file simutaneously.png

Share this post


Link to post
Share on other sites

Thank you everyone. I should have insisted more on the fact that my issue is really with INI file. The only reason why I am tinkering with text file VIs is that they are the blocs used by the INI library. This new screenshot and attached VI shows that relationship. The 2 While loops are equivalent. The Text VIs of the top loop are the ones I found in the INI VIs of the bottom loop.

As you can see, both loops encounter the same random rate of failure. In the case of the INI, the text VI returns an empty string, and therefore the INI VI tells us the key is not found. So my problem is not fixed yet. It seems I need a locking mechanism to prevent the reading and the writing of the INI file to happen at the same time.

 

Read-Write TXT issue.vi

Capture1.PNG

Share this post


Link to post
Share on other sites
17 minutes ago, Manudelavega said:

Thank you everyone. I should have insisted more on the fact that my issue is really with INI file. The only reason why I am tinkering with text file VIs is that they are the blocs used by the INI library. This new screenshot and attached VI shows that relationship. The 2 While loops are equivalent. The Text VIs of the top loop are the ones I found in the INI VIs of the bottom loop.

As you can see, both loops encounter the same random rate of failure. In the case of the INI, the text VI returns an empty string, and therefore the INI VI tells us the key is not found. So my problem is not fixed yet. It seems I need a locking mechanism to prevent the reading and the writing of the INI file to happen at the same time.

 

Read-Write TXT issue.vi

Capture1.PNG

You're doing several errors here. The main error is that you access a global resource concurrently without any protection of it. The File IO VIs have a built in protection with the deny and access rights but since you do no error handling you simply miss it completely that something went wrong. 

Basically without error cluster fed through the VIs you are totally bound to fail without good indication. There is nothing fundamentally wrong with the File IO functions but the way you try to use them simply can't work. A file is just as a global variable a global resource and needs to be treated like one. If you don't watch out you create race conditions and in this case since the File IO functions do some resource locking to prevent the worst to happen also errors that you don't handle at all.

Both the Open Configuration File and the Close Configuration File can fail if the file is open at that moment by another function. If the Open Configuration File function fails you have to retry opening it until it succeeds before you can read any data. If the Close Configuration File function fails with the write if modified set to True  you have to equally retry it, otherwise the data you modified in the INI file data is not written back to the file on disk.

Again, only the Open Configuration File and Close Configuration File actually access the file on disk at all. Everything else is done in memory. Open Configuration File opens the file for reading and will fail if the file is currently open for writing by a Close Configuration File function that needs to save some data back to the file. And Close Configuration File will open the file for read/write which will fail if anyone has that file already opened no matter if it is just for reading or also read/write access.

Edited by rolfk

Share this post


Link to post
Share on other sites

Thanks rolfk, my real code has error handling but my example doesn't generate any error so I omitted the error handling on purpose for higher readability. Taking a step back: all I want to do is to rely on a configuration file to store parameters. I have been counting on the possibility to have several pieces of code asynchronously either writing or reading one parameter (not the same one). Was I wrong to count on this possibility? How do you manipulate your INI files? Do you wrap the INI Vis inside your own API?

Share this post


Link to post
Share on other sites

Your assumption is not fully safe. File IO is protected and if your application can happen to access the same file from multiple locations asynchronously you do have to employ some protection.

Most of the times I have actually LV 2 style globals that manage a certain subset of ini settings for an application. Each of them has a initialize method, a get and set method and a save method and if there is a change that some information needs to be modified asynchronously a specific modify method for such information.

The initialize method does read the configuration into the uninitialized shift register and is typically executed during program initialization, the save method saves the content of the shift register to the INI file section that it handles and is sometimes called at the end of the application and whenever the user changed a setting in the configuration.

For program runtime variables that you want to save somehow to some persistent file storage you should do something similar but you might need to do also some kind of resource locking if you intend to read the value do something with it and then save it back. The reading of the LV 2 style global does not require to actually read in the value from disk as it is already stored but you may have to distinguish between just reading for reference whatever is the current value in which case you simply read the LV 2 style variable and reading it in order to modify it and write it back in which case you may need to acquire also a semaphore that is then released after you have written the value back.

Share this post


Link to post
Share on other sites

Thanks, you confirm my suspicion about the need for a locking mechanism like a semaphore or a LV 2 global. I thought I could get by without one, I was wrong :unsure:

Share this post


Link to post
Share on other sites

I would just create a simple DVR reference class that handles the INI file.
You can just use the IPE-Node structure as your semaphore.

Share this post


Link to post
Share on other sites

Thanks for the idea, but since I never leave the file open, I will make it as easy as possible and simply create a FGV2 with only 2 cases: Read Key and Write Key.

Read Key will do Open/Read/Close

Write Key will do Open/Write/Close

That should do the trick.

Share this post


Link to post
Share on other sites

If going that far, I would just add the Open and Close cases as well and then just leave the file open.  It would be a little faster as it avoids all of the opening the file and parsing the data etc.

Share this post


Link to post
Share on other sites
20 minutes ago, crossrulz said:

If going that far, I would just add the Open and Close cases as well and then just leave the file open.  It would be a little faster as it avoids all of the opening the file and parsing the data etc.

Good point, but I see 2 issues:

- this would prevent the ability to open the file in notepad and change a key manually

- if the application process is killed in the windows task manager, all changes will be lost since we never execute the INI Close, which is the only case to actually write to the file

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.