Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,19 +94,9 @@ private static bool DirectoryExists(string fullPath)
return ((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR);
}

/// <summary>Opens a SafeFileHandle for a file descriptor created by a provided delegate.</summary>
/// <param name="fdFunc">
/// The function that creates the file descriptor. Returns the file descriptor on success, or an invalid
/// file descriptor on error with Marshal.GetLastWin32Error() set to the error code.
/// </param>
/// <returns>The created SafeFileHandle.</returns>
internal static SafeFileHandle Open(Func<SafeFileHandle> fdFunc)
{
SafeFileHandle handle = Interop.CheckIo(fdFunc());

Debug.Assert(!handle.IsInvalid, "File descriptor is invalid");
return handle;
}
// Each thread will have its own copy. This prevents race conditions if the handle had the last error.
[ThreadStatic]
internal static Interop.ErrorInfo? t_lastCloseErrorInfo;

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

Expand Down
14 changes: 14 additions & 0 deletions src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,20 @@ protected override void Dispose(bool disposing)
// name will be removed immediately.
Interop.Sys.Unlink(_path); // ignore errors; it's valid that the path may no longer exist
}

// Closing the file handle can fail, e.g. due to out of disk space
// Throw these errors as exceptions when disposing
if (_fileHandle != null && !_fileHandle.IsClosed && disposing)
{
SafeFileHandle.t_lastCloseErrorInfo = null;

_fileHandle.Dispose();

if (SafeFileHandle.t_lastCloseErrorInfo != null)
{
throw Interop.GetExceptionForIoErrno(SafeFileHandle.t_lastCloseErrorInfo.GetValueOrDefault(), _path, isDirectory: false);
}
}
}
}
finally
Expand Down