changeset 24604:6b3c78f84d3b

allow octave_sleep to be interruptible (bug #52876) * utils.cc (octave_sleep): Break sleep interval up into smaller segments and check for interrupts between each segment.
author John W. Eaton <jwe@octave.org>
date Mon, 15 Jan 2018 16:38:16 -0500
parents 845ec6f4fb96
children a27dcb26f872
files libinterp/corefcn/utils.cc
diffstat 1 files changed, 43 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/utils.cc	Mon Jan 15 08:08:32 2018 -0800
+++ b/libinterp/corefcn/utils.cc	Mon Jan 15 16:38:16 2018 -0500
@@ -1347,28 +1347,63 @@
   return retval;
 }
 
+// FIXME: sleep is complicated because we want it to be interruptible.
+// With the way this program handles signals, the sleep system call
+// won't respond to SIGINT.  Maybe there is a better way than
+// breaking this up into multiple shorter intervals?
+
 void
 octave_sleep (double seconds)
 {
   if (seconds <= 0)
     return;
 
+  // Split delay into whole seconds and the remainder as a decimal
+  // fraction.
+
   double fraction = std::modf (seconds, &seconds);
-  fraction = std::floor (fraction * 1000000000); // nanoseconds
+
+  // Further split the fractional seconds into whole tenths and the
+  // nearest number of nanoseconds remaining.
+
+  double tenths = 0;
+  fraction = std::modf (fraction * 10, &tenths) / 10;
+  fraction = std::round (fraction * 1000000000);
+
+  // Sleep for the hundredths portion.
+
+  struct timespec hundredths_delay = { 0, static_cast<long> (fraction) };
+
+  nanosleep (&hundredths_delay, nullptr);
+
+  // Sleep for the whole tenths portion, allowing interrupts every
+  // tenth.
+
+  struct timespec one_tenth = { 0, 100000000 };
+
+  for (int i = 0; i < static_cast<int> (tenths); i++)
+    {
+      nanosleep (&one_tenth, nullptr);
+
+      octave_quit ();
+    }
+
+  // Sleep for the whole seconds portion, allowing interrupts every
+  // tenth.
 
   time_t sec = ((seconds > std::numeric_limits<time_t>::max ())
                 ? std::numeric_limits<time_t>::max ()
                 : static_cast<time_t> (seconds));
 
-  struct timespec delay = { sec, static_cast<long> (fraction) };
-  int status;
-
-  do
+  for (time_t s = 0; s < sec; s++)
     {
-      status = octave_nanosleep_wrapper (&delay, &delay);
-      octave_quit ();
+      for (int i = 0; i < 10; i++)
+        {
+          nanosleep (&one_tenth, nullptr);
+
+          octave_quit ();
+        }
     }
-  while (status == -1 && errno == EINTR);
 }
 
 DEFUN (isindex, args, ,