- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Race conditions ftw :D
Admin
Well surprisingly this seems to be the correct way for checking if a file is in use according to: http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use
I had a similar issue where I wrote a program for a closed system: When a technician plugged in a USB drive (only they had access to the USB ports) the system automatically checked the drive for an update file. The problem was that the anti-virus seemed to be quicker sometimes and lock the file for access. Thus I needed a way to check when the file became available. I used the method above.
I must say I used a loop in conjunction with a fail timer (if the file did not become available after a few seconds).
Admin
Basically, this means that they bought cc-wiki licensed code without the required attribution? :p
Admin
I wouldn't do that, at least not with closing the stream after checking. What happens if another process is locking the file just right after your check and before reopening the stream?
Admin
I would be interested in the code she used instead. Whenever I need to check for file locks in C# I use the try-catch statement, too. Thanks in advance
Admin
stream = file.Open(FileMode.Open, FileAccess.ReadWriteFrist, FileShare.None);
Admin
The problem is that the very notion of "checking if a file is" whatever, before you do an operation, is not correct in the first place (so a "correct way" to do it is meaningless). You try with the semantics you need (e.g. tell to write, or tell to write without overwriting if there is already a file), then handle failure.
In some cases you need to do some checks, e.g. to check the temporary file you opened is not a symlink to another part of the file system, for security reasons, but you do so after you opened the file (since it's not going to change once you opened it).
Notice you might want to know whether the fiile doesn't exist, or you lack permissions to open it or write to it or anything else, and therefore do checks on files without opening or whatever (which may include a try-catch), but you do so only for user indication, as part of the "handle failure" thing, you do not take any decision based on these extra checks.
Admin
It appears as if that's the true source of this code, even the comment is identical.
Admin
Right, everybody go to that question and upvote the actually correct answer, which is slightly further down. We can fix this!
Admin
How does this give you a stutus? It just throws the exception ;-)
Admin
Admin
((Many years ago, I worked on an on-access A/V scanner for a major vendor of the time. Not the actual scanning component, but the component that captured file access calls on Win95, so I know something about what's needed.))
Admin
Hey guys, have you heard about that awesome invention? It's called a mutex and it's really cool.
Admin
Oh, wait, I know this one! Since isFileOpen is a boolean function...
Admin
Oh, please tell me the filesystem API you are using so that I can trivially DOS attack everything that uses it by taking that mutex then never releasing it.
Admin
Me too; true, false, FileNotFound.
Admin
(of course this side discussion barely applies here, since the "first trying something" in today's WTF does involve an exception itself, and is apparently the «"“correct”"» way to do such a check)
Admin
Oh, wait! Both posts were by the same person?
What, did you take a nap and forget what you already posted?
Admin
Unless you have some stupendously fast harddrives, I'd wager that the time spent with throwing an exception is easily eaten by the time spent doing I/O, thus I dub this worry as premature optimization.
Admin
Kids are TRWTF, AJ. I mean, what useful purpose do they serve, other than to make a mess of the place you had to move to because his bachelor pad wasn't "homey" enough, destroy all the expensive crap you made him buy you, and leave the lights and TV on until they're old enough to finance a major drug addiction?
Admin
This brings back misty memories of:
As it turned out, this approach was particularly handy in Atari DOS when you needed to open the second file with the exact same name. Just keep looping past the first one.
And how do you get two files with the same name? Easy:
Admin
I know this one, I have two myself.
Uh. wait- uh..
Admin
Admin
INH! TRRrrrRRuuuust mmeeee!
Admin
try catch block is acceptable method of handling this situation. what else could AJ do?
Admin
I figured that since the code comments said "another thread", they meant that another thread in the same application can be using this file. If another application is using the file, catch the exception and show an error message, there's nothing more to do anyway.
Admin
No one complains about TRWTF?
WriteToFile happily returns without any exception or other indication that the write was not successful if the file is locked!
Admin
The only time I've seen anyone actually upset by the try/handle-failure pattern (whether in its C#/Java incarnation or its classic C incarnation) was with someone who was complaining that the software was filling up the audit log, which was recording every single failing system call. That was definitely TRWTF. Also a facepalm moment.
Admin
Admin
Uh, just put the try-catch around the original open()? Makes no sense to do an open just to see if it works, then close and reopen. Oh, and handle the exception a little more detailed than just an IO exception maybe.
Admin
I see no WTF in the method copy/pasted from Stack Overflow.
The thing with file locks is that they are a filesystem way of addressing the 'Dining Philosophers' problem, where of n entities, only one can 'eat' from the plate at a time, while the others think.
A race condition is somewhat inherent in the setup; if you try accessing a file before the lock has been removed by the current consumer, well, you shouldn't be able to access it. That try/catch block looks for the lock, and if it detects that the file is locked, tells the app that the file...is locked. Pretty self explanatory.
What did AJ do to it, remove the comments?
Admin
It is the correct way to check if a file is locked if, presumably, the purpose is that if it is not locked you open it and perform some operation with it.
Because if you call some method that returns a boolean that says it is not locked, then you may try opening it only to find that a race condition has occurred and it now really is locked.
So if you are going to handle that condition anyway, just open it.
If you don't really want to do anything with the file but are asserting a file is not locked as part of some unit test, then do what this does by all means. Who cares if it takes a few extra resources, it's a unit test.
File system operations are likely to be far more expensive than any call-stack unwinding that takes place during an exception. I find in general that developers generally are told that exceptions are inefficient and therefore tend to avoid using them for premature optimisation. I do not recall a time where I optimised an application where I did it by removing exceptions (i.e. I found exceptions were making the code slow).
I have also never seen exception safety making code slow. (Weak exception safety is not an issue in C# but if you want a strong exception guarantee that applies in C# too).
Admin
So the real wtf is the spurious inclusion of husband and kids, in order to make tenuous metaphor with code, amirite?
Admin
FileStream stream = null;
Never seen the point of this, the object is null if uninitilized anyway and you've taken out a compiler check (in Java) by intializing to null
Admin
Thread A: if (!IsFileLocked()) { int a = ReadFile(filePath); WriteFile(filePath, a+1); }
Thread B: if (!IsFileLocked()) { int a = ReadFile(filePath); WriteFile(filePath, a+1); }
Execution order: A: if(!IsFileLocked()) // opens file, returns true closes file B: if(!IsFileLocked()) // A closed file, B opens file, returns true, closes file A: int a = ReadFile // a = 1; B: int a = ReadFile // a = 1; A: WriteFile(... 2); // Opens file, begins to write... B: WriteFile(... 2); // File IO Exception, fails to write...
Not only did they both try to write the number 2, instead of 3 being written by one of them, B threw a file exception...
Double WTF
Admin
I have some annoying blood relatives as well. Also, I have had to work with some annoying code.
These are related, because both are annoying; its almost as if the relatives are a living breathing embodiment of the the code, and the code is a sort of mathematical representation of the relatives.
I think I've made my point.
Admin
The correct API if you want a safe way without exceptions is a try_lock() method.
This returns to you immediately whether or not you have successfully locked. If you have you can use the file and need to unlock. If not you can choose to wait or move on to do something else.
C doesn't have exceptions and POSIX has try_lock for mutex and the concept can be applied for other resource locks too.
I don't know the C# library so I don't know if it exists there.
Admin
Admin
I've used this exact snippet. Here's a scenario: I'm batch processing files that are dumped into a share by photo copiers. However, sometimes when the batch is kicked off, the photo copiers will still be transferring a file. So, if a file is locked, just kick it to the end of the line and if it's still locked after processing everything else do an exponential back off. The key thing in my situation though, is that there is only one thing that will be locking the file so race conditions aren't a big deal.
Admin
The right answer to that questions is actually the answer to another question: http://stackoverflow.com/a/3202085/137451.
Admin
For those that still think Exceptions are 'expensive', I suggest you read the below before trying to optimize them out.
http://www.developerfusion.com/article/5250/exceptions-and-performance-in-net/
(TLDR: Exceptions are only expensive in a) loops that throw 1000's of them, and b) in the debugger)
Admin
You're really, really lucky then. I had a system that was brought to a grinding halt just from the exceptions inherent in the utility methods used thousands of times per postback. Fixing those improved the speed of the app to the point where it was actually usable, and actually, was quite impressive.
I know that's probably an "edge" case, but you have to remember that 80% of developers can't program, so there will be a ton of apps like that.
Admin
The purpose of children is so that, when you retire, there is someone to pay social security taxes to support you.
Glad I was able to clear that up for you.
Admin
Hmm, this code is certainly flawed. If you test if you can open the file, and then if you can you go ahead and open the file, you create the possibility of a race problem, where someone else manages to lock the file or delete it or otherwise make it unopenable in between your test and your attempt at actual execution. The right way to do this is to try to open the file and catch the exception on the attempted open.
Also, if the file does not exist, then retrying the operation is not likely to be useful if you do nothing to create the file. Well, unless we're expecting that there is some other process that creates the file.
But the point of the article seems to be to ridicule the idea of retrying repeatedly after a failure. But if a likely cause of failure is that the file is locked out by another process, what would you suggest as an alternative? If there are multiple apps that occasionally lock a file and write to it, should we abort if we find that someone else has the file at the moment? Why? Just keep trying until it's free. I've done this many times. I always put some upper limit on it so it doesn't keep trying for hours.
I'd be interested to see what her "correct" code was.
Admin
Unfortunately for me, all I have are nieces and nephews (SIGH).
Please note that this thread might wander into Godwins law very quickly if we aren't careful.
Lastly: The Muppet show was REAL COOL for both adults and kids!
Admin
Admin
Admin
Admin
Not a big deal - until it is. So why not just solve it properly in the first place? Its not like the solution is difficult.
Admin
Interesting that a file is defined as "locked" if it doesn't exist. Is there even a way to reproduce this in a way that wouldn't be prone to race-conditions?