aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-03-17 12:40:02 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-03-17 12:40:02 +0200
commit5a686c5460e9fbb32af5014d0dbf1169ea301ec2 (patch)
treeaa219f442926ef4879acb2c14f7eead47f9f3d33
parentde09beabe1448e9c6b401ec9acdd69ee5bf0f0e2 (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.cxx20
-rw-r--r--build2/context2
-rw-r--r--build2/test/rule.cxx6
-rw-r--r--build2/test/script/parser.cxx35
-rw-r--r--build2/utility1
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()