Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does .NET Standard normalize HResult values across every platform it supports?

I am creating a simple function that creates a random file. To be thread safe, it creates the file in a retry loop and if the file exists it tries again.

while (true)
{
    fileName = NewTempFileName(prefix, suffix, directory);

    if (File.Exists(fileName))
    {
        continue;
    }

    try
    {
        // Create the file, and close it immediately
        using (var stream = new FileStream(fileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
        {
            break;
        }
    }
    catch (IOException e)
    {
        // If the error was because the file exists, try again
        if ((e.HResult & 0xFFFF) == 0x00000050)
        {
            continue;
        }

        // else rethrow it
        throw;
    }
}

According to MSDN, the HResult value is derived from COM which would seem to indicate it will only work on Windows, and it specifically lists them as "Win32 codes". But this is in a library which targets .NET Standard and ideally it should work on every platform .NET Standard supports.

What I am wondering is whether I can rely on the above approach that uses the value from HResult to be cross-platform? The documentation is not clear on this point.

If not, how do I determine what HResult values to expect on other platforms?

NOTE: There is a similar question Does .NET define common HRESULT values?, but it was asked before .NET Standard (and cross-platform support for .NET) existed, so I cannot rely on that answer for this purpose.

For now, our codebase only uses:

  1. 0x00000020 - ERROR_SHARING_VIOLATION
  2. 0x00000021 - ERROR_LOCK_VIOLATION
  3. 0x00000050 - ERROR_FILE_EXISTS

We are targeting .NET Standard 1.5.

NOTE: While the accepted answer does satisfy what I asked here, I have a follow-up question How do I make catching generic IOExceptions reliably portable across platforms?

like image 725
NightOwl888 Avatar asked Sep 23 '17 14:09

NightOwl888


1 Answers

Exception.HResult values are not standardized across platforms.

For I/O errors, .NET Core will return platform specific error code as HResult. The value of HResult property for file already exist in your example is going be 17 on Linux, and it may be different value for other Unix systems.

The relevant code that maps IO errors to exceptions on Unix is here: https://github.com/dotnet/corefx/blob/master/src/Common/src/Interop/Unix/Interop.IOErrors.cs

like image 52
Jan Kotas Avatar answered Sep 19 '22 20:09

Jan Kotas