From defebbd4c75d43ad2d171cccbcc7ed737ff8a035 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 20 Jan 2020 12:22:49 +0000 Subject: [PATCH] jobs: If multiple jobs fail, save and print all the exceptions. Don't "forget" earlier exceptions. --- src/jobs.ml | 25 +++++++++++++++++-------- tests/20-multiple-failures.gl | 27 +++++++++++++++++++++++++++ tests/20-multiple-failures.sh | 27 +++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 tests/20-multiple-failures.gl create mode 100755 tests/20-multiple-failures.sh diff --git a/src/jobs.ml b/src/jobs.ml index 249ab6a..f5aefa9 100644 --- a/src/jobs.ml +++ b/src/jobs.ml @@ -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 index 0000000..e87129e --- /dev/null +++ b/tests/20-multiple-failures.gl @@ -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 index 0000000..e8cfcc2 --- /dev/null +++ b/tests/20-multiple-failures.sh @@ -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 -- 1.8.3.1