Blob Blame History Raw
Bug fixes from the 5.6-fixes git branch.  This currently contains the
following bug fixes.

commit 167eaf7d283c6077b12e0b37dd7512a3163488c9
Author: David Matthews <dm@prolingua.co.uk>
Date:   Mon Apr 25 19:09:14 2016 +0100

    Only return the "status" value from "wait" if the result is non-zero.
    The calling code in the Posix structure converts the status result to a
    value of type exit_status even if the pid is zero.  The result is
    ignored in that case but it can result in a Fail exception if the
    status is invalid.
    
    (cherry picked from commit ba608ceb1dbc20db934bd01b0bccdd50c08ac4e9)
    
    # Conflicts:
    #   libpolyml/unix_specific.cpp

commit 3dea3b67470777d5dca3108cd957129464e8c2e6
Author: David Matthews <dm@prolingua.co.uk>
Date:   Fri Apr 22 14:15:17 2016 +0100

    Ensure the save vector is reset when sleeping in Posix.Process.sleep.
    This is almost the same as commit 57bc974 in basicio.cpp.
    
    (cherry picked from commit a66e52345ab56fe0af3e4862bb61a7f98a3da1db)
    
    # Conflicts:
    #   libpolyml/unix_specific.cpp

commit 3bd62174b2a306be50ed0b42f9ff783e6fd0218c
Author: James Clarke <jrtc27@jrtc27.com>
Date:   Tue Apr 12 21:58:22 2016 +0100

    Fix threadExited and interrupt_requested overlapping
    
    HAVE_PTHREAD isn't necessarily defined when processes.h is included, as
    it is defined in processes.cpp, but not when included by interpret.cpp.
    As a result, the root thread can believe that an interrupted thread has
    been killed, prematurely deleting its task data. This fixes #9.
    
    (cherry picked from commit 4ce6eee5829c256da2d2709787e19ea83a56f48c)

diff --git a/Tests/Fail/Test073.ML b/Tests/Fail/Test073.ML
new file mode 100644
index 0000000..d9bf6fc
--- /dev/null
+++ b/Tests/Fail/Test073.ML
@@ -0,0 +1,5 @@
+(* Testing Posix is a problem because the Posix structure is not available in Windows. *)
+(* This caused an assertion failure when the save vector overflowed. *)
+Posix.Process.sleep (Time.fromMilliseconds 15000);
+rubbish; (* Generate a "failure" i.e. the correct result *)
+
diff --git a/libpolyml/processes.h b/libpolyml/processes.h
index bf7dfc8..3bc7711 100644
--- a/libpolyml/processes.h
+++ b/libpolyml/processes.h
@@ -172,7 +172,7 @@ private:
 #ifdef HAVE_WINDOWS_H
     LONGLONG lastCPUTime; // Used for profiling
 #endif
-#ifdef HAVE_PTHREAD
+#if ((!defined(_WIN32) || defined(__CYGWIN__)) && defined(HAVE_LIBPTHREAD) && defined(HAVE_PTHREAD_H))
 public:
     bool threadExited;
 private:
diff --git a/libpolyml/unix_specific.cpp b/libpolyml/unix_specific.cpp
index a2624d8..095444e 100644
--- a/libpolyml/unix_specific.cpp
+++ b/libpolyml/unix_specific.cpp
@@ -383,7 +383,6 @@ static void restoreSignals(void)
 Handle OS_spec_dispatch_c(TaskData *taskData, Handle args, Handle code)
 {
     unsigned lastSigCount = receivedSignalCount; // Have we received a signal?
-    TryAgain:
     int c = get_C_long(taskData, DEREFWORDHANDLE(code));
     switch (c)
     {
@@ -580,27 +579,30 @@ Handle OS_spec_dispatch_c(TaskData *taskData, Handle args, Handle code)
         }
 
     case 21: /* Pause until signal. */
-        {
             /* This never returns.  When a signal is handled it will
                be interrupted. */
+       while (true)
+       {
             processes->ThreadPause(taskData);
             if (lastSigCount != receivedSignalCount)
                 raise_syscall(taskData, "Call interrupted by signal", EINTR);
-            goto TryAgain;
-        }
+       }
 
     case 22: /* Sleep until given time or until a signal.  Note: this is called
             with an absolute time as an argument and returns a relative time as
             result.  This RTS call is tried repeatedly until either the time has
             expired or a signal has occurred. */
+        while (true)
         {
             struct timeval tv;
             /* We have a value in microseconds.  We need to split
                it into seconds and microseconds. */
+            Handle hSave = taskData->saveVec.mark();
             Handle hTime = args;
             Handle hMillion = Make_arbitrary_precision(taskData, 1000000);
             unsigned long secs = get_C_ulong(taskData, DEREFWORDHANDLE(div_longc(taskData, hMillion, hTime)));
             unsigned long usecs = get_C_ulong(taskData, DEREFWORDHANDLE(rem_longc(taskData, hMillion, hTime)));
+            taskData->saveVec.reset(hSave);
             /* Has the time expired? */
             if (gettimeofday(&tv, NULL) != 0)
                 raise_syscall(taskData, "gettimeofday failed", errno);
@@ -613,11 +615,13 @@ Handle OS_spec_dispatch_c(TaskData *taskData, Handle args, Handle code)
                 processes->ThreadPause(taskData);
                 if (lastSigCount != receivedSignalCount)
                     raise_syscall(taskData, "Call interrupted by signal", EINTR);
-                goto TryAgain;
+                // And loop
+            }
+            else
+            {
+                processes->TestAnyEvents(taskData); // Check for interrupts anyway
+                return Make_arbitrary_precision(taskData, 0);
             }
-            else processes->TestAnyEvents(taskData); // Check for interrupts anyway
-
-            return Make_arbitrary_precision(taskData, 0);
         }
     
     case 23: /* Set uid. */
@@ -1252,7 +1256,7 @@ TryAgain:
     int callFlags = get_C_long(taskData, DEREFHANDLE(args)->Get(2));
     int flags = callFlags | WNOHANG; // Add in WNOHANG so we never block.
     pid_t pres = 0;
-    int status;
+    int status = 0;
     switch (kind)
     {
     case 0: /* Wait for any child. */
@@ -1288,7 +1292,7 @@ TryAgain:
     {
         Handle result, pidHandle, resHandle;
         pidHandle = Make_arbitrary_precision(taskData, pres);
-        resHandle = Make_arbitrary_precision(taskData, status);
+        resHandle = Make_arbitrary_precision(taskData, pres == 0 ? 0: status);
 
         result = ALLOC(2);
         DEREFHANDLE(result)->Set(0, DEREFWORDHANDLE(pidHandle));