Hello,
I just ran into a weird problem with FileStream. The problem occurs in
the following scenario:
- I create an instance of FileStream and use it to write to a disk
with a just a small amount of free space.
- When the disk gets full, FileStream throws an IOException. I catch
and process it.
- My program continue executing. At some later point, I'm getting an
unhandled IOException (althoug the whole code is wrapped in try-catch
block).
- After inspecting the call stack and the running threads I made the
following observations:
--- The second exception occurs in a thread which doesn't belong to my
process.
--- The call stack of the thread in which this exception occurs starts
within the FileStream finalize method.
By observing the calls in the call stack, I believe that what happen
is as follows:
When the disk gets full and the first exception (that I handle)
occurs, the buffer of the FileStream object is not empty. However,
since the object gets out of scope, the garbage collector tries to
release it at some point. The garbage collector calls finalize, which
calls dispose, and one of the calls in this sequense is a call to
flush() that tries to write the buffer before killing the object.
Since the disk is full, this call fails and an IOException is thrown
from the garbage collector thread.
I found no way to get around this, except from disabling garbage
collection for the FileStream objec, which IMHO is pretty ugly. If the
garbage collector and FileStream always work in this way, i.e. the GC
calls finalize, which causes flush to be called without knowing that
the disk is already full and a previous write failed, then it seems
like a bug in the framework.
I would appreciate any comments,
TIA,
Amit
P.s. Below is the code I've been using for demonstrating this problem:
static void Main(string[] args)
{
try
{
FileStream fs =
new FileStream(args[0], FileMode.Create);
Console.WriteLine("starting to write...");
while (true)
fs.WriteByte(0xff);
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}",
e.Message);
}
Console.WriteLine("press any key to continue");
Console.Read();
}
Anthony Moore - 14 Aug 2003 23:37 GMT
This is an excellent analysis of what is happening and it looks like a
genuine bug. This looks like all the information will would need to
reproduce and fix it. I have passed this on to the owners of FileStream, so
hopefully this can be fixed in the next version.
Thank you.
--------------------
| From: amit@notalvision.com (Amit)
| Newsgroups: microsoft.public.dotnet.framework.clr
| Subject: Unhandled exception in FileStream when writing to a full disk -
bug in framework?
| Date: 23 Jul 2003 04:30:59 -0700
| Organization: http://groups.google.com/
[quoted text clipped - 4 lines]
| Content-Transfer-Encoding: 8bit
| X-Trace: posting.google.com 1058959860 3678 127.0.0.1 (23 Jul 2003
11:31:00 GMT)
| X-Complaints-To: groups-abuse@google.com
| NNTP-Posting-Date: 23 Jul 2003 11:31:00 GMT
| Path:
cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!newsfeed00.sul.t-online.de!t-onlin
e.de!diablo.theplanet.net!colt.net!peernews-us.colt.net!newsfeed.news2me.com
!newsfeed2.easynews.com!newsfeed1.easynews.com!easynews.com!easynews!sn-xit-
02!sn-xit-06!sn-xit-09!supernews.com!postnews1.google.com!not-for-mail
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.clr:7430
| X-Tomcat-NG: microsoft.public.dotnet.framework.clr
[quoted text clipped - 64 lines]
|
| }
Anthony Moore - 14 Aug 2003 23:39 GMT
To work around this problem, I would recommend trying to close the file on
the same thread you catch the exception instead of waiting for the GC
finalizer to do this. This is good practice for other reasons (predictable
behavior and performance).
--------------------
| From: amit@notalvision.com (Amit)
| Newsgroups: microsoft.public.dotnet.framework.clr
| Subject: Unhandled exception in FileStream when writing to a full disk -
bug in framework?
| Date: 23 Jul 2003 04:30:59 -0700
| Organization: http://groups.google.com/
[quoted text clipped - 4 lines]
| Content-Transfer-Encoding: 8bit
| X-Trace: posting.google.com 1058959860 3678 127.0.0.1 (23 Jul 2003
11:31:00 GMT)
| X-Complaints-To: groups-abuse@google.com
| NNTP-Posting-Date: 23 Jul 2003 11:31:00 GMT
| Path:
cpmsftngxa06.phx.gbl!TK2MSFTNGP08.phx.gbl!newsfeed00.sul.t-online.de!t-onlin
e.de!diablo.theplanet.net!colt.net!peernews-us.colt.net!newsfeed.news2me.com
!newsfeed2.easynews.com!newsfeed1.easynews.com!easynews.com!easynews!sn-xit-
02!sn-xit-06!sn-xit-09!supernews.com!postnews1.google.com!not-for-mail
| Xref: cpmsftngxa06.phx.gbl microsoft.public.dotnet.framework.clr:7430
| X-Tomcat-NG: microsoft.public.dotnet.framework.clr
[quoted text clipped - 64 lines]
|
| }
Amit Ramon - 17 Aug 2003 10:59 GMT
Anthony,
I didn't use Close() in the example just for simplicity. Usually I would
close the FileStream in a finally block. However, this doesn't at all
help in this situation. If you call Close() after getting a disk full
exception, Close() will fail since it will try to write the buffer, The
FileStream will remain un-closed, and the finalizer will still try to
flush the buffer.
Amit