350f91e
Bug fixes from the 5.6-fixes git branch.  This currently contains the
350f91e
following bug fixes.
350f91e
350f91e
commit 167eaf7d283c6077b12e0b37dd7512a3163488c9
350f91e
Author: David Matthews <dm@prolingua.co.uk>
350f91e
Date:   Mon Apr 25 19:09:14 2016 +0100
350f91e
350f91e
    Only return the "status" value from "wait" if the result is non-zero.
350f91e
    The calling code in the Posix structure converts the status result to a
350f91e
    value of type exit_status even if the pid is zero.  The result is
350f91e
    ignored in that case but it can result in a Fail exception if the
350f91e
    status is invalid.
350f91e
    
350f91e
    (cherry picked from commit ba608ceb1dbc20db934bd01b0bccdd50c08ac4e9)
350f91e
    
350f91e
    # Conflicts:
350f91e
    #   libpolyml/unix_specific.cpp
350f91e
350f91e
commit 3dea3b67470777d5dca3108cd957129464e8c2e6
350f91e
Author: David Matthews <dm@prolingua.co.uk>
350f91e
Date:   Fri Apr 22 14:15:17 2016 +0100
350f91e
350f91e
    Ensure the save vector is reset when sleeping in Posix.Process.sleep.
350f91e
    This is almost the same as commit 57bc974 in basicio.cpp.
350f91e
    
350f91e
    (cherry picked from commit a66e52345ab56fe0af3e4862bb61a7f98a3da1db)
350f91e
    
350f91e
    # Conflicts:
350f91e
    #   libpolyml/unix_specific.cpp
350f91e
350f91e
commit 3bd62174b2a306be50ed0b42f9ff783e6fd0218c
350f91e
Author: James Clarke <jrtc27@jrtc27.com>
350f91e
Date:   Tue Apr 12 21:58:22 2016 +0100
350f91e
350f91e
    Fix threadExited and interrupt_requested overlapping
350f91e
    
350f91e
    HAVE_PTHREAD isn't necessarily defined when processes.h is included, as
350f91e
    it is defined in processes.cpp, but not when included by interpret.cpp.
350f91e
    As a result, the root thread can believe that an interrupted thread has
350f91e
    been killed, prematurely deleting its task data. This fixes #9.
350f91e
    
350f91e
    (cherry picked from commit 4ce6eee5829c256da2d2709787e19ea83a56f48c)
350f91e
350f91e
diff --git a/Tests/Fail/Test073.ML b/Tests/Fail/Test073.ML
350f91e
new file mode 100644
350f91e
index 0000000..d9bf6fc
350f91e
--- /dev/null
350f91e
+++ b/Tests/Fail/Test073.ML
350f91e
@@ -0,0 +1,5 @@
350f91e
+(* Testing Posix is a problem because the Posix structure is not available in Windows. *)
350f91e
+(* This caused an assertion failure when the save vector overflowed. *)
350f91e
+Posix.Process.sleep (Time.fromMilliseconds 15000);
350f91e
+rubbish; (* Generate a "failure" i.e. the correct result *)
350f91e
+
350f91e
diff --git a/libpolyml/processes.h b/libpolyml/processes.h
350f91e
index bf7dfc8..3bc7711 100644
350f91e
--- a/libpolyml/processes.h
350f91e
+++ b/libpolyml/processes.h
350f91e
@@ -172,7 +172,7 @@ private:
350f91e
 #ifdef HAVE_WINDOWS_H
350f91e
     LONGLONG lastCPUTime; // Used for profiling
350f91e
 #endif
350f91e
-#ifdef HAVE_PTHREAD
350f91e
+#if ((!defined(_WIN32) || defined(__CYGWIN__)) && defined(HAVE_LIBPTHREAD) && defined(HAVE_PTHREAD_H))
350f91e
 public:
350f91e
     bool threadExited;
350f91e
 private:
350f91e
diff --git a/libpolyml/unix_specific.cpp b/libpolyml/unix_specific.cpp
350f91e
index a2624d8..095444e 100644
350f91e
--- a/libpolyml/unix_specific.cpp
350f91e
+++ b/libpolyml/unix_specific.cpp
350f91e
@@ -383,7 +383,6 @@ static void restoreSignals(void)
350f91e
 Handle OS_spec_dispatch_c(TaskData *taskData, Handle args, Handle code)
350f91e
 {
350f91e
     unsigned lastSigCount = receivedSignalCount; // Have we received a signal?
350f91e
-    TryAgain:
350f91e
     int c = get_C_long(taskData, DEREFWORDHANDLE(code));
350f91e
     switch (c)
350f91e
     {
350f91e
@@ -580,27 +579,30 @@ Handle OS_spec_dispatch_c(TaskData *taskData, Handle args, Handle code)
350f91e
         }
350f91e
 
350f91e
     case 21: /* Pause until signal. */
350f91e
-        {
350f91e
             /* This never returns.  When a signal is handled it will
350f91e
                be interrupted. */
350f91e
+       while (true)
350f91e
+       {
350f91e
             processes->ThreadPause(taskData);
350f91e
             if (lastSigCount != receivedSignalCount)
350f91e
                 raise_syscall(taskData, "Call interrupted by signal", EINTR);
350f91e
-            goto TryAgain;
350f91e
-        }
350f91e
+       }
350f91e
 
350f91e
     case 22: /* Sleep until given time or until a signal.  Note: this is called
350f91e
             with an absolute time as an argument and returns a relative time as
350f91e
             result.  This RTS call is tried repeatedly until either the time has
350f91e
             expired or a signal has occurred. */
350f91e
+        while (true)
350f91e
         {
350f91e
             struct timeval tv;
350f91e
             /* We have a value in microseconds.  We need to split
350f91e
                it into seconds and microseconds. */
350f91e
+            Handle hSave = taskData->saveVec.mark();
350f91e
             Handle hTime = args;
350f91e
             Handle hMillion = Make_arbitrary_precision(taskData, 1000000);
350f91e
             unsigned long secs = get_C_ulong(taskData, DEREFWORDHANDLE(div_longc(taskData, hMillion, hTime)));
350f91e
             unsigned long usecs = get_C_ulong(taskData, DEREFWORDHANDLE(rem_longc(taskData, hMillion, hTime)));
350f91e
+            taskData->saveVec.reset(hSave);
350f91e
             /* Has the time expired? */
350f91e
             if (gettimeofday(&tv, NULL) != 0)
350f91e
                 raise_syscall(taskData, "gettimeofday failed", errno);
350f91e
@@ -613,11 +615,13 @@ Handle OS_spec_dispatch_c(TaskData *taskData, Handle args, Handle code)
350f91e
                 processes->ThreadPause(taskData);
350f91e
                 if (lastSigCount != receivedSignalCount)
350f91e
                     raise_syscall(taskData, "Call interrupted by signal", EINTR);
350f91e
-                goto TryAgain;
350f91e
+                // And loop
350f91e
+            }
350f91e
+            else
350f91e
+            {
350f91e
+                processes->TestAnyEvents(taskData); // Check for interrupts anyway
350f91e
+                return Make_arbitrary_precision(taskData, 0);
350f91e
             }
350f91e
-            else processes->TestAnyEvents(taskData); // Check for interrupts anyway
350f91e
-
350f91e
-            return Make_arbitrary_precision(taskData, 0);
350f91e
         }
350f91e
     
350f91e
     case 23: /* Set uid. */
350f91e
@@ -1252,7 +1256,7 @@ TryAgain:
350f91e
     int callFlags = get_C_long(taskData, DEREFHANDLE(args)->Get(2));
350f91e
     int flags = callFlags | WNOHANG; // Add in WNOHANG so we never block.
350f91e
     pid_t pres = 0;
350f91e
-    int status;
350f91e
+    int status = 0;
350f91e
     switch (kind)
350f91e
     {
350f91e
     case 0: /* Wait for any child. */
350f91e
@@ -1288,7 +1292,7 @@ TryAgain:
350f91e
     {
350f91e
         Handle result, pidHandle, resHandle;
350f91e
         pidHandle = Make_arbitrary_precision(taskData, pres);
350f91e
-        resHandle = Make_arbitrary_precision(taskData, status);
350f91e
+        resHandle = Make_arbitrary_precision(taskData, pres == 0 ? 0: status);
350f91e
 
350f91e
         result = ALLOC(2);
350f91e
         DEREFHANDLE(result)->Set(0, DEREFWORDHANDLE(pidHandle));