diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-03-17 12:40:02 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-03-17 12:40:02 +0200 |
commit | 5a686c5460e9fbb32af5014d0dbf1169ea301ec2 (patch) | |
tree | aa219f442926ef4879acb2c14f7eead47f9f3d33 | |
parent | de09beabe1448e9c6b401ec9acdd69ee5bf0f0e2 (diff) |
Catch and dump unhandled exceptions in async task functions
The problem with relying on noexcept for this is that there is no stack.
-rw-r--r-- | build2/algorithm.cxx | 20 | ||||
-rw-r--r-- | build2/context | 2 | ||||
-rw-r--r-- | build2/test/rule.cxx | 6 | ||||
-rw-r--r-- | build2/test/script/parser.cxx | 35 | ||||
-rw-r--r-- | build2/utility | 1 |
5 files changed, 49 insertions, 15 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index 4e5ec78..9357632 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -485,6 +485,12 @@ namespace build2 t.state_ = target_state::failed; l.offset = target::offset_applied; } + catch (const std::exception& e) + { + *diag_stream << "unhandled exception: " << e; + assert (false); + abort (); + } return t.state_; } @@ -537,7 +543,9 @@ namespace build2 // if (sched.async (start_count, *task_count, - [a] (target& t, size_t offset, const diag_frame* ds) + [a] (target& t, + size_t offset, + const diag_frame* ds) noexcept { diag_frame df (ds); phase_lock pl (run_phase::match); @@ -779,6 +787,12 @@ namespace build2 { ts = t.state_ = target_state::failed; } + catch (const std::exception& e) + { + *diag_stream << "unhandled exception: " << e; + assert (false); + abort (); + } // Decrement the task count (to count_executed) and wake up any threads // that might be waiting for this target. @@ -864,10 +878,10 @@ namespace build2 // if (sched.async (start_count, *task_count, - [a] (target& t, const diag_frame* ds) + [a] (target& t, const diag_frame* ds) noexcept { diag_frame df (ds); - execute_impl (a, t); // Note: noexcept. + execute_impl (a, t); }, ref (t), diag_frame::stack)) diff --git a/build2/context b/build2/context index bc73d5b..95030d8 100644 --- a/build2/context +++ b/build2/context @@ -138,7 +138,7 @@ namespace build2 // for (...) // { // sched.async (task_count, - // [] (...) + // [] (...) noexcept // { // phase_lock pl (run_phase::match); // (2) // ... diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx index 5cec891..0e1aff6 100644 --- a/build2/test/rule.cxx +++ b/build2/test/rule.cxx @@ -397,6 +397,12 @@ namespace build2 { r = scope_state::failed; } + catch (const std::exception& e) + { + *diag_stream << "unhandled exception: " << e; + assert (false); + abort (); + } return r; } diff --git a/build2/test/script/parser.cxx b/build2/test/script/parser.cxx index d004223..0555f2f 100644 --- a/build2/test/script/parser.cxx +++ b/build2/test/script/parser.cxx @@ -2867,6 +2867,26 @@ namespace build2 exec_scope_body (); } + static void + execute_impl (scope& s, script& scr, runner& r) noexcept + { + try + { + parser p; + p.execute (s, scr, r); + } + catch (const failed&) + { + s.state = scope_state::failed; + } + catch (const std::exception& e) + { + *diag_stream << "unhandled exception: " << e; + assert (false); + abort (); + } + } + void parser:: exec_scope_body () { @@ -2983,20 +3003,13 @@ namespace build2 // bail out if we weren't asked to keep going. // if (!sched.async (task_count, - [] (scope& s, script& scr, runner& r, + [] (scope& s, + script& scr, + runner& r, const diag_frame* ds) noexcept { diag_frame df (ds); - - try - { - parser p; - p.execute (s, scr, r); - } - catch (const failed&) - { - s.state = scope_state::failed; - } + execute_impl (s, scr, r); }, ref (*chain), ref (*script_), diff --git a/build2/utility b/build2/utility index aec3806..0c129c4 100644 --- a/build2/utility +++ b/build2/utility @@ -10,6 +10,7 @@ #include <string> // to_string() #include <utility> // move(), forward(), declval(), make_pair() #include <cassert> // assert() +#include <cstdlib> // abort() #include <iterator> // make_move_iterator() #include <algorithm> // * #include <functional> // ref(), cref() |