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));