Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 8775efa

Browse files
authored
Merge pull request #28099 from carlossanlop/FileStreamDispose
[release/3.1] [coreclr] Fix FileStream.Dispose silently fails on Dispose when disk has run out of space
2 parents 3fbe134 + 25fee4f commit 8775efa

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -94,19 +94,9 @@ private static bool DirectoryExists(string fullPath)
9494
return ((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR);
9595
}
9696

97-
/// <summary>Opens a SafeFileHandle for a file descriptor created by a provided delegate.</summary>
98-
/// <param name="fdFunc">
99-
/// The function that creates the file descriptor. Returns the file descriptor on success, or an invalid
100-
/// file descriptor on error with Marshal.GetLastWin32Error() set to the error code.
101-
/// </param>
102-
/// <returns>The created SafeFileHandle.</returns>
103-
internal static SafeFileHandle Open(Func<SafeFileHandle> fdFunc)
104-
{
105-
SafeFileHandle handle = Interop.CheckIo(fdFunc());
106-
107-
Debug.Assert(!handle.IsInvalid, "File descriptor is invalid");
108-
return handle;
109-
}
97+
// Each thread will have its own copy. This prevents race conditions if the handle had the last error.
98+
[ThreadStatic]
99+
internal static Interop.ErrorInfo? t_lastCloseErrorInfo;
110100

111101
protected override bool ReleaseHandle()
112102
{
@@ -122,7 +112,10 @@ protected override bool ReleaseHandle()
122112
// to retry, as the descriptor could actually have been closed, been subsequently reassigned, and
123113
// be in use elsewhere in the process. Instead, we simply check whether the call was successful.
124114
int result = Interop.Sys.Close(handle);
125-
Debug.Assert(result == 0, $"Close failed with result {result} and error {Interop.Sys.GetLastErrorInfo()}");
115+
if (result != 0)
116+
{
117+
t_lastCloseErrorInfo = Interop.Sys.GetLastErrorInfo();
118+
}
126119
return result == 0;
127120
}
128121

src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,20 @@ protected override void Dispose(bool disposing)
267267
// name will be removed immediately.
268268
Interop.Sys.Unlink(_path); // ignore errors; it's valid that the path may no longer exist
269269
}
270+
271+
// Closing the file handle can fail, e.g. due to out of disk space
272+
// Throw these errors as exceptions when disposing
273+
if (_fileHandle != null && !_fileHandle.IsClosed && disposing)
274+
{
275+
SafeFileHandle.t_lastCloseErrorInfo = null;
276+
277+
_fileHandle.Dispose();
278+
279+
if (SafeFileHandle.t_lastCloseErrorInfo != null)
280+
{
281+
throw Interop.GetExceptionForIoErrno(SafeFileHandle.t_lastCloseErrorInfo.GetValueOrDefault(), _path, isDirectory: false);
282+
}
283+
}
270284
}
271285
}
272286
finally

0 commit comments

Comments
 (0)