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?

Recommended Answers

All 16 Replies

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?

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)

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 you unlink(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.

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.

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?

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 is BEING deleted.

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?

>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.

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.

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.

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.

>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 [I]some exception[/I];

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

stream.exceptions(ios_base::failbit | ios_base::bad_bit);

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.

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.

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?

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].

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.