[mono][threads] save/restore errno in thread state transitions (#79856)
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Wed, 12 Jul 2023 15:44:31 +0000 (11:44 -0400)
committerGitHub <noreply@github.com>
Wed, 12 Jul 2023 15:44:31 +0000 (11:44 -0400)
commitf1d0dfe17a22f619d4c78128a669bd3d13407b6c
tree0a5ee3b0a285b297c498b303da42280f135d9de8
parent693eef6417353d45d126fa05365665bccf5b82d9
[mono][threads] save/restore errno in thread state transitions (#79856)

* [threads] Save errno when using posix semaphores for thread transitions

   We already save/restore GetLastError on win32.  Do it on posix platforms, too.

   If one thread is in a pinvoke wrapper, while another thread triggers a STW, the pinvoke wrapper will self-suspend the thread and wait for a notification to resume.  Depending on the platform we can use win32 primitives, Mach semaphores or POSIX semaphores.  win32 and posix can both change the value of last error (errno, respectively) while the thread is suspended.

   That means that code like this (generated by the LibraryImportAttribute source generator) cannot reliably retrieve the error from the last pinvoke:

   ```csharp
   __retVal = __PInvoke(__path_native, mode); // there is a pinvoke wrapper here, that transitions from GC Safe to GC Unsafe mode
   __lastError = System.Runtime.InteropServices.Marshal.GetLastSystemError();
   ```

   The solution is to explicitly preserve the value of GetLastError/errno when exiting from GC Safe.

   Fixes https://github.com/dotnet/runtime/issues/77364

* rename W32_DEFINE_LAST_ERROR_RESTORE_POINT to MONO_DEFINE_LAST_ERROR_RESTORE_POINT

   and W32_RESTORE_LAST_ERROR_FROM_RESTORE_POINT to MONO_RESTORE_LAST_ERROR_FROM_RESTORE_POINT
src/mono/mono/utils/mono-threads-coop.c
src/mono/mono/utils/mono-threads.c
src/mono/mono/utils/mono-threads.h