How to avoid intermittent Errno::ETXTBSY exceptions? - ruby-on-rails

During part of a request in a Rails application, I copy a directory from one place to another, think of it like a working area. Sometimes this copy operation results in "Errno::ETXTBSY" exceptions being thrown. I can't seem to pin down the case that causes it, any tips to detect the case or avoid it altogether?
I've made sure the destination directory is uniquely named, so it shouldn't be a case of 2 processes attempting to write to the same place. Beyond that I'm out of ideas.

ETXTBSY means that you're trying to open for writing a file which is currently being executed as a program, or that you're trying to execute a file which is currently open for writing. Since you say you're copying files, not executing them it seems likely it's the former, not the later.
You say you're targeting a unique new destination, but my guess is that's not entirely true and you're actually targeting an existing directory and one of the files you're attempting to overwrite is currently open as an executable text segment of a running process.
You haven't posted any code, so it's hard to comment specifically. I suggest you add enough logging so you know exactly what file(s) are being processed and specifically, the source and destination path that throws the exception. Then you could use lsof to see what process may have that file open.
One way to avoid the problem if you are overwriting a currently open executable, is to first unlink the target file. The running process will still have the old inode mapped and proceed merrily using the deleted file, but your open for write will then create a new file which won't conflict.

Related

having external files in an electron application

I have an electron app, and when I make it, it packages and compiles everything.
Sounds like it works perfectly right?
Well, problem is I want one of the folders to not be compiled, but still be accessible by my static files, so the users can add or remove content from the folders.
I've tried making it in a seperate folder, but then it can't find the files even when it's placed in the correct relative path.
Overall, I want my app to exist next to a folder and my <script src="./folder/script.js"></script> to actually be able to access it.
I'm new to basically anything node or electron so i'm probably making some dumb mistake.
Thanks in advance.
Having your user touching files close to your Electron application may be fraught with danger. If they accidently overwrite an important file or accidently delete an important file then your application may stop working and require the user to perform a re-install.
Instead, have any default files the user may need to "touch" packaged up with your application and then upon your applications first run, copy these files (and any necessary folder structure) over to the users home, desktop, documents, downloads or even userData directory.
That way, your application will always know where to find them and the directory is a directory your user will already be comfortable adding files to and removing files from.
You can always let the use choose where these files are stored as a settings option which persists in an application setting file, using something similar to path.join(app.getPath('userData'), 'settings.json');
See Electron's app.getPath(name) for more information.

Write files changes made when opening file through windows explorer in a mapped drive

I'm implementing a WebDAV file server using the ITHit WebDave engine, i have the following problem
When i list the files and open one of them i get the ReadAsync method called, i provide the content and the file is opened correctly
However any changes i make to the file can't be saved, i get an error saying
A device attached to the system is not working
I looked at the file system samples and implemented support based on the FileSystemStorage.AspNetCore sample,
From what can understand the WriteAsync method is used when creating new files, should i expect for WriteAsync to also be called for file edits that need to be changed?
Am i wrong in the assumption that DavFile.WriteAsync will be called with a stream for the updated content?
If WriteAsync is not the right location to save updates to a file, could you provide some guidance on the process of saving changes to existing files?
Edited to add:
Now i can see that after i dismiss the first error about the device not working i get the standard save dialog box, if i click save it asks me if i want to overwrite the existing file, after accepting to overwrite then WriteAsync is called and i can update the file contents
I'm not quite sure why it would first tell me there's an error and then still allow me to write the file but only as replacement to the original file
Thanks for your help
Fixed, i found that there were issues with the ILockAsync implementation, reviewing the FileSystemStorage sample helped fix the issue with locking files before writing or updating properties

How to get a content of file which is being written by an application?

This application always create a file when you activate a function (lets say, a log file). This file cannot be opened during the running - but I need its content before application closes (another process uses it, so I cant even view it). Is there a way to "hook" it somehow?
Im working with Delphi, but I accept any other solution.
So, summary, I need to know what file application created (it always creates other, but in the same directory) and the content it wrote. Any help appreciated.
I found a workaround:
copy the file, and operate on the cloned one:
http://www.howtogeek.com/howto/windows-vista/backupcopy-files-that-are-in-use-or-locked-in-windows/

How can a program change its own resources?

I would like to store some XML program preferences as a resource in a Delphi application. The resource would be modified based on user changes. I have no problem creating the XML and loading it as a resource, and can modify the xmlDocument that I load it into, but I don't know how to write the document back. Is this even possible? I would prefer not to end up with 2 files in the end (.exe and .xml).
The answer is both yes and no.
Yes, it is possible to update resources in a binary using Windows API routines. This link to BeginUpdateResource() should get you on the right track on that score.
However, you will note the following condition on the use of BeginUpdateResource():
"The binary file in which to update resources. An application must be
able to obtain write-access to this file; the file referenced by
pFileName cannot be currently executing."
In other words, it is not possible for an application to simply update it's own resources while running.
There are a number of strategies you could employ to achieve what you want - or something close enough to it as to be satisfactory. Which is most appropriate will depend on your precise needs.
Of the multitude of solutions, two might be:
1) Maintain all such resources in a DLL (resource only DLL - containing no actual code as such) which you open only when specifically loading resources (or updating them). Thus at the time you wish to write a resource back to the DLL you should be able to get the required write-lock.
or
2) When you need to update a resource rename the current running EXE to something like "myapp.OLD", copy it so that you have a new file with the current name "myapp.exe". You can then update "myapp.exe" because it is actually "myapp.old" that is executing.
This second approach is quite messy and has a "nasty smell" but is a technique that is (or used to be) quite commonly used by auto-updaters, for example. Obviously will involve a restart of your app at some point if the current running code is to make use of the updated resources in the modified EXE, so it may not be appropriate to your needs.
Something else to consider is that anti-virus software may flag the activity as suspicious.
Thinking about Deltics' answer I thought you could also create a console application that writes your resource back to the main exe. So your main exe saves it's changes to a file and also extracts the console app. When the main application terminates it calls the console app. The console app waits for a short period of time and then binds the resource file to the main executable, deletes the resource file and itself. The console app could do a check to make sure that the resource file was written successfully and, if not, leave the resource file open. The main executable could see the resource file upon start up and use it instead of the embedded file - as a safeguard.
All of this assumes a single user application.

Need help opening printer spool shadow file (.SHD) that is locked

I'm interested in some information inside a shadow file (.shd) located inside the windows print spooling directory "C:\Windows\System32\spool\PRINTERS". Every time a print job is started, a spool file (.spl) and a shadow file (.shd) are created in that directory. So far I have been successful in detecting when a print job has started, and have been able to pause that print job. If you don't pause the job, the files eventually make their way to the printer and then are deleted by windows.
My problem is. I cannot open the .SHD files because they are locked in such a way that you can not read them while they are open by the sprint spooler. I've even tried going to the file in windows explorer and simply copying the file to another file, and that didn't work either. The .SPL spool files I can open though. I simply wait, and fairly quickly the spooler release that file. For the shadow file though, it permanently holds on to this file. Unfortunately, its the one I need.
The line of code I'm using specifically to open the file is as follows:
m_spoolJobStream = new FileStream(spoolFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
The IOException I get is:
The process cannot access the file 'C:\Windows\system32\spool\PRINTERS\FP00083.SHD' because it is being used by another process.
So yes, it is being used by another process. Its being used by the window's print spooler service. But I don't think there is anything I can do about that. All I want to do is read the file. I don't want to make any changes to it. Is there anything I can do here or am I just screwed?
Check the option: "Keep printed documents" (if you have HP printer) and then see your spool file folder, both shadow and spool files would be there.
Well, I did not find a way around this problem. I suspect there is no solution for this and it is by design. However I did find another way to get the information I wanted (at least it seems so thus far).
I'm using the FindNextPrinterChangeNotification() routine out of the winspool.drv library. This guy returns a pointer to a PRINTER_NOTIFY_INFO structure, which in turn contains an array of PRINTER_NOTIFY_INFO_DATA structures. Within that array, there is an element with its "Field" member marked as "JOB_NOTIFY_FIELD_DEVMODE". This element contains a fairly large structure of type DEVMODE. The structure is explained by M$ here http://msdn.microsoft.com/en-us/library/dd183565%28v=vs.85%29.aspx . This structure looks like it contains what I'm looking for and apparently is wrapped up in the .SHD file anyways according to this page http://www.undocprint.org/formats/winspool/shd. I'd like to know what else is in that .SHD file, but I still can't open it because its locked while the job is paused, and I suspect that it stays locked until the job is complete. Oh well, I think my new solution is more elegant anyways.
Just make sure you pause the job in the spool on BOTH your box and the server, then you should be able to copy/open/move the shd file just like you can the spl file. Worked for me, anyway...
This works for me:
- Hang your printer (e.g. jam the paper)
- Print and observe .SHD and .SPL being created
- Stop Print Spooler
- Open the file
The problem might be the FileShare.ReadWrite parameter. You're asking to read and write on the file and maybe that's why you get an error. You should try asking for read-only permission.

Resources