From c936709e28d97b777a2b12ac8471b64bcb72aa7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Tue, 9 Feb 2016 14:11:28 +0100
Subject: [PATCH] Filesystem.Monitor: Improved robustness.

It seems ADT.Heap()->peek() sometimes can index the NULL value
(cf [bug 7644]). The most likely cause is that the last element
of the heap was removed by a different thread during the call.
Inhibit propagation of the error to the caller.

Work around for [bug 7644].
---
 .../Filesystem.pmod/Monitor.pmod/basic.pike   | 35 ++++++++++++-------
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike b/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike
index ded753a2a9..ab891b5d77 100644
--- a/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike
+++ b/lib/modules/Filesystem.pmod/Monitor.pmod/basic.pike
@@ -1490,19 +1490,28 @@ int check(int|void max_wait, int|void max_cnt,
     int cnt;
     int t = time();
     if (sizeof(monitor_queue)) {
-      Monitor m;
-      while ((m = monitor_queue->peek()) && (m->next_poll <= t)) {
-	cnt += check_monitor(m);
-	if (!(--scan_cnt)) {
-	  m = monitor_queue->peek();
-	  break;
-	}
-      }
-      if (m) {
-	ret = m->next_poll - t;
-	if (ret <= 0) ret = 1;
-      } else {
-	scan_cnt--;
+      // NB: peek() can apparently in some circumstances throw errors.
+      //     cf [bug 7644]. The likely cause being that a different
+      //     thread removed the last element during the call. Make
+      //     sure not to propagate the error to the caller.
+      mixed err = catch {
+	  Monitor m;
+	  while ((m = monitor_queue->peek()) && (m->next_poll <= t)) {
+	    cnt += check_monitor(m);
+	    if (!(--scan_cnt)) {
+	      m = monitor_queue->peek();
+	      break;
+	    }
+	  }
+	  if (m) {
+	    ret = m->next_poll - t;
+	    if (ret <= 0) ret = 1;
+	  } else {
+	    scan_cnt--;
+	  }
+	};
+      if (err) {
+	master()->handle_error(err);
       }
     }
     if (cnt || !scan_wait || !scan_cnt) {
-- 
GitLab