jobs: If multiple jobs fail, save and print all the exceptions.
authorRichard W.M. Jones <rjones@redhat.com>
Mon, 20 Jan 2020 12:22:49 +0000 (12:22 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Mon, 20 Jan 2020 12:30:54 +0000 (12:30 +0000)
Don't "forget" earlier exceptions.

src/jobs.ml
tests/20-multiple-failures.gl [new file with mode: 0644]
tests/20-multiple-failures.sh [new file with mode: 0755]

index 249ab6a..f5aefa9 100644 (file)
@@ -29,7 +29,7 @@ let run next_job retire_job string_of_job =
   let lock = Mutex.create () and cond = Condition.create () in
 
   (* If a job throws an exception it is saved here. *)
-  let last_exn = ref None in
+  let last_exn = ref [] in
 
   (* This is the background thread which runs each job. *)
   let runner (job, f) =
@@ -38,7 +38,7 @@ let run next_job retire_job string_of_job =
     Mutex.lock lock;
     (match exn with
      | None -> retire_job job
-     | Some exn -> last_exn := Some exn
+     | Some exn -> last_exn := exn :: !last_exn
     );
     decr running;
     Condition.signal cond;
@@ -46,7 +46,7 @@ let run next_job retire_job string_of_job =
   in
 
   let rec loop () =
-    if !last_exn = None then (
+    if !last_exn = [] then (
       match next_job () with
       | Complete -> ()
       | Not_ready ->
@@ -78,10 +78,19 @@ let run next_job retire_job string_of_job =
     Condition.wait cond lock
   done;
 
-  let exn = !last_exn in
+  let exns = !last_exn in
   Mutex.unlock lock;
 
-  (* Re-raise the saved exception from the job which failed. *)
-  match exn with
-  | None -> ()
-  | Some exn -> raise exn
+  (* Re-raise the saved exception(s) from the job(s) which failed. *)
+  match exns with
+  | [] -> ()
+  | [exn] -> raise exn
+  | exns ->
+     (* Combine the multiple exceptions into a single Failure exn. *)
+     let exns = List.rev exns in
+     let exn_to_string = function
+       | Failure s -> s
+       | exn -> Printexc.to_string exn in
+     let exns = List.map exn_to_string exns in
+     let exns = String.concat "\n" exns in
+     raise (Failure exns)
diff --git a/tests/20-multiple-failures.gl b/tests/20-multiple-failures.gl
new file mode 100644 (file)
index 0000000..e87129e
--- /dev/null
@@ -0,0 +1,27 @@
+# Goals test.
+# Copyright (C) 2020 Richard W.M. Jones
+# Copyright (C) 2020 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# Multiple failures should all be reported in the error message.
+
+goal all = : fail ("1"), fail ("2"), fail ("3")
+
+goal fail (n) = {
+    sleep 1
+    echo FAIL %n
+    exit 1
+}
diff --git a/tests/20-multiple-failures.sh b/tests/20-multiple-failures.sh
new file mode 100755 (executable)
index 0000000..e8cfcc2
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+# Goals test.
+# Copyright (C) 2020 Richard W.M. Jones
+# Copyright (C) 2020 Red Hat Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+set -x
+
+goals -j 4 -f 20-multiple-failures.gl > 20-multiple-failures.out 2>&1 ||:
+fgrep 'fail ("1")' 20-multiple-failures.out
+fgrep 'fail ("2")' 20-multiple-failures.out
+fgrep 'fail ("3")' 20-multiple-failures.out
+rm 20-multiple-failures.out