954,498 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

ofstream - detect if file has been deleted between open and close

As seen in another thread, I'm working on a Log class. I'm running into an issue that if I delete the file that's being written to, the Log class doesn't detect it and continues to 'think' it's writing even though the file is gone... (Note that this is on sun solaris in case it matters)

I've tried the following to try and detect this
(assuming my ofstream is named out)
!out.is_open()
!out.good()
out.fail()

None of them seem to detect this issue. (Nor changing the permissions to non-write while the file has already been opened by the app). Note that these functions DO catch a problem with opening the file, but not when it's already opened. Any advice?

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 
As seen in another thread, I'm working on a Log class. I'm running into an issue that if I delete the file that's being written to, the Log class doesn't detect it and continues to 'think' it's writing even though the file is gone... (Note that this is on sun solaris in case it matters) I've tried the following to try and detect this (assuming my ofstream is named out) !out.is_open() !out.good() out.fail() None of them seem to detect this issue. (Nor changing the permissions to non-write while the file has already been opened by the app). Note that these functions DO catch a problem with opening the file, but not when it's already opened. Any advice?

Why not close the file descriptor?

subtronic
Junior Poster
117 posts since Aug 2003
Reputation Points: 44
Solved Threads: 1
 

Not sure I follow. I have a program that is writing/appending to a file every second (as a test). In another window/session, I'm deleting that file via the rm command in unix. I want my program to detect that it can no longer write to the file. instead, it just keeps on writing. (Though nothing is actually written as the file is gone)

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 
Not sure I follow. I have a program that is writing/appending to a file every second (as a test). In another window/session, I'm deleting that file via the rm command in unix. I want my program to detect that it can no longer write to the file. instead, it just keeps on writing. (Though nothing is actually written as the file is gone)

So, in *nix, when you open a file descriptor, you grab a reference to that file. Thus, when youunlink(2) that file using the "rm" command, you're only dropping that reference. Because you have a stream open (and another reference), the file will not actually be removed [yet]. Once you close the stream, you will release that reference, and presumably at that point the file's reference count will then drop to 0 and be "removed".

Ah reference counting, fun for the entire family.

subtronic
Junior Poster
117 posts since Aug 2003
Reputation Points: 44
Solved Threads: 1
 

What you want to do is not possible in standard C++. You seem to think that a file stream knows if the external device is available if you remove it between construction and destruction of the stream. In reality, all you're doing is invoking undefined behavior by writing to a device that you've told the stream exists and will continue to exist until destruction. That's an implied contract when you open a file stream and you're not adhering to it.

My kneejerk reaction to this problem is to tell you not to delete the file until you're done with it. However, you can do a platform dependent test to see if the file exists before every operation on it. However, that's inefficient and just sweeps the dirt under the rug.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

I was only deleting it to see if my class would detect it. So what you're saying is that it can't detect the deletion, or a change in permissions, etc. What about running out of disk space?

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 
I was only deleting it to see if my class would detect it. So what you're saying is that it can't detect the deletion, or a change in permissions, etc. What about running out of disk space?

So, if you're writing a program that's specific to a "unix" system why not use C and OS libraries?? And, like I told you, your concept and understanding of "deletion" is wrong. You can't detect deletion because nothing isBEING deleted.

subtronic
Junior Poster
117 posts since Aug 2003
Reputation Points: 44
Solved Threads: 1
 

I'm not using C because my Log class uses inheritance to either be a screen, or a file (and eventually a socket, or a database, etc..)

By the way, if not for detecting problems writing, what's the point of the .bad() and .fail() functions? When would they be used?

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

>So what you're saying is that it can't detect the deletion, or a change in permissions, etc
Did I studder?
What you want to do is not possible in standard C++.
>What about running out of disk space
That will cause failbit (and possibly badbit) to be set.

>By the way, if not for detecting problems writing, what's the point of the .bad() and .fail() functions?
You're confusing errors during legitimate use with blatant and intentional breaking of the rules.

Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

You certainly didn't 'studder', you might have 'stuttered' ;)

In any case, I'm not expecting blatant breaking of the rules, I'm only trying to emulate failure conditions to test the code.

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 
In any case, I'm not expecting blatant breaking of the rules, I'm only trying to emulate failure conditions to test the code.

You're trying to emulate failure conditions when no failure condition has occured. Sounds mighty stupid to me.

subtronic
Junior Poster
117 posts since Aug 2003
Reputation Points: 44
Solved Threads: 1
 

I see your point - I guess I'll just leave the .fail() checks in there and should they ever occur it will at least throw an exception.

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 

>should they ever occur it will at least throw an exception.
Only if you tell it to either through an explicit test:

if (stream.fail())
  throw <em>some exception</em>;

Or tell the stream to throw exceptions (which it doesn't do by default):

stream.exceptions(ios_base::failbit | ios_base::bad_bit);
Narue
Bad Cop
Administrator
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
 

Yes, I'm throwing the exception - that's what all this is about. My initial issue was that I wanted to test my exceptions when I had a problem with opening, writing, or closing a file. I was attempting (apparently foolishly) to cause this situations to test the code.

winbatch
Posting Pro in Training
466 posts since Feb 2005
Reputation Points: 68
Solved Threads: 18
 
Yes, I'm throwing the exception - that's what all this is about. My initial issue was that I wanted to test my exceptions when I had a problem with opening, writing, or closing a file. I was attempting (apparently foolishly) to cause this situations to test the code.

Just create and open a file (which gets a reference to it, and associates it with a new file descriptor), remove the file (drops the reference count by 1), close the file descriptor (drops the reference count to 0), and try to open it again. You should then see the expected error.

There's an inherent advantage to doing systems related programming in C especially on an operating system that was written in C. It's quite easy to do the abstraction you want where a "Log" can be a file or a socket or a database using a C struct and union and pointers :-). But its not as intuitive as it is in C++, admittedly.

subtronic
Junior Poster
117 posts since Aug 2003
Reputation Points: 44
Solved Threads: 1
 

Why not open test and close the file each time you write to it it high overhead and useless in the real world im sure but if you really want to know if the file is there that seems to be the best way to do it.
Just so that im understanding subtronic when the file is deleted its only deleted for the future not for programs currently running using the file, so if a file disappeared while being written to that would mean that the there had to be some kind of physical damage to the drive. Are these assumptions correct?

sinrtb
Light Poster
32 posts since Apr 2005
Reputation Points: 10
Solved Threads: 0
 
Just so that im understanding subtronic when the file is deleted its only deleted for the future not for programs currently running using the file, so if a file disappeared while being written to that would mean that the there had to be some kind of physical damage to the drive. Are these assumptions correct?

Sorta. A reference count keeps track of how many "things" are using that object. So, when you go to _remove_ a file in the file system, with say, "rm" you send to the kernel the unlink() system-call. The unlink() system-call does all its magic and at some point it puts back its reference to the file. At this stage the operating system asks, "Is anybody still using this file?" If there is indeed someone else using the file (ie: the reference count is still > 0) then deletion of the file is deferred. When that someone is finished using the file, they return their reference and by doing so, the reference count drops to 0 and the file is safely deleted. Thus, when you open a stream (fstream::open, open, fopen) you're grabbing a reference and preventing the object from being destroyed [by removal from the file system].

subtronic
Junior Poster
117 posts since Aug 2003
Reputation Points: 44
Solved Threads: 1
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You