Save the Win32 error code where necessary
authorSimon Marlow <simonmar@microsoft.com>
Fri, 26 Jan 2007 16:26:20 +0000 (16:26 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Fri, 26 Jan 2007 16:26:20 +0000 (16:26 +0000)
Similarly to the way we save errno across context switches and
suspendThread/resumeThread, we must save and restore the Win32 error
code via GetLastError()/SetLastError().  Fixes #896.

includes/TSO.h
rts/Schedule.c

index 3f7923d..088097e 100644 (file)
@@ -159,6 +159,9 @@ typedef struct StgTSO_ {
 #ifdef DIST
     StgTSODistInfo dist;
 #endif
+#ifdef mingw32_HOST_OS
+    StgWord32 saved_winerror;
+#endif
 
     /* The thread stack... */
     StgWord32         stack_size;     /* stack size in *words* */
index c068919..a7a0f33 100644 (file)
@@ -588,6 +588,10 @@ run_thread:
     prev_what_next = t->what_next;
 
     errno = t->saved_errno;
+#if mingw32_HOST_OS
+    SetLastError(t->saved_winerror);
+#endif
+
     cap->in_haskell = rtsTrue;
 
     dirtyTSO(t);
@@ -637,6 +641,10 @@ run_thread:
     // XXX: possibly bogus for SMP because this thread might already
     // be running again, see code below.
     t->saved_errno = errno;
+#if mingw32_HOST_OS
+    // Similarly for Windows error code
+    SetLastError(t->saved_winerror);
+#endif
 
 #if defined(THREADED_RTS)
     // If ret is ThreadBlocked, and this Task is bound to the TSO that
@@ -2283,9 +2291,17 @@ void *
 suspendThread (StgRegTable *reg)
 {
   Capability *cap;
-  int saved_errno = errno;
+  int saved_errno;
   StgTSO *tso;
   Task *task;
+#if mingw32_HOST_OS
+  StgWord32 saved_winerror;
+#endif
+
+  saved_errno = errno;
+#if mingw32_HOST_OS
+  saved_winerror = GetLastError();
+#endif
 
   /* assume that *reg is a pointer to the StgRegTable part of a Capability.
    */
@@ -2330,6 +2346,9 @@ suspendThread (StgRegTable *reg)
 #endif
 
   errno = saved_errno;
+#if mingw32_HOST_OS
+  SetLastError(saved_winerror);
+#endif
   return task;
 }
 
@@ -2338,8 +2357,16 @@ resumeThread (void *task_)
 {
     StgTSO *tso;
     Capability *cap;
-    int saved_errno = errno;
     Task *task = task_;
+    int saved_errno;
+#if mingw32_HOST_OS
+    StgWord32 saved_winerror;
+#endif
+
+    saved_errno = errno;
+#if mingw32_HOST_OS
+    saved_winerror = GetLastError();
+#endif
 
     cap = task->cap;
     // Wait for permission to re-enter the RTS with the result.
@@ -2367,6 +2394,9 @@ resumeThread (void *task_)
     cap->r.rCurrentTSO = tso;
     cap->in_haskell = rtsTrue;
     errno = saved_errno;
+#if mingw32_HOST_OS
+    SetLastError(saved_winerror);
+#endif
 
     /* We might have GC'd, mark the TSO dirty again */
     dirtyTSO(tso);