Merge pull request #4333 from ntherning/Mono-Posix-Stdlib-do-not-clobber-Marshal...
authorNiklas Therning <niklas@therning.org>
Wed, 8 Feb 2017 10:16:17 +0000 (11:16 +0100)
committerGitHub <noreply@github.com>
Wed, 8 Feb 2017 10:16:17 +0000 (11:16 +0100)
Make sure Stdlib.GetLastError() never clobbers Marshal.GetLastWin32Error()

mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs

index 9b95fba6f3c115923b9c1b1c1e3722326f145f43..dbabb29c7f1b70c9544914abb197388d7af0a1ab 100644 (file)
@@ -426,14 +426,20 @@ namespace Mono.Unix.Native {
 
                public static Errno GetLastError ()
                {
+                       // Always call Marshal.GetLastWin32Error() before the OS check,
+                       // even on Windows where we don't use the return value. If we do
+                       // the OS check first Environment.OSVersion (if it happens to be
+                       // the first ever access) will clobber Marshal.GetLastWin32Error()
+                       // and we won't get the desired errno value on non-Windows platforms.
+                       int errno = Marshal.GetLastWin32Error ();
                        if (Environment.OSVersion.Platform != PlatformID.Unix) {
                                // On Windows Marshal.GetLastWin32Error() doesn't take errno
                                // into account so we need to call Mono_Posix_Stdlib_GetLastError()
                                // which returns the value of errno in the C runtime
                                // libMonoPosixHelper.dll was linked against.
-                               return (Errno) _GetLastError ();
+                               errno = _GetLastError ();
                        }
-                       return NativeConvert.ToErrno (Marshal.GetLastWin32Error ());
+                       return NativeConvert.ToErrno (errno);
                }
 
                [DllImport (MPH, CallingConvention=CallingConvention.Cdecl,