async: context: allow run re-entrance
Switch the context call so that it can be re-entrant. A single call
to `run` will either:
1. Process until the context is successfully stopped.
2. An exception is raised from a spawned task.
If an exception is raised, it could be caught outside the run call
and then run called again.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: Icd05df421a1f0592bd2390fbe8e21a16252eafed
diff --git a/test/async/context.cpp b/test/async/context.cpp
index 34e5bb0..b60cc38 100644
--- a/test/async/context.cpp
+++ b/test/async/context.cpp
@@ -34,6 +34,24 @@
runToStop();
}
+TEST_F(Context, ReentrantRun)
+{
+ runToStop();
+ for (int i = 0; i < 100; ++i)
+ {
+ ctx->run();
+ }
+}
+
+TEST_F(Context, SpawnThrowingTask)
+{
+ ctx->spawn(std::execution::just() |
+ std::execution::then([]() { throw std::logic_error("Oops"); }));
+
+ EXPECT_THROW(runToStop(), std::logic_error);
+ ctx->run();
+}
+
TEST_F(Context, SpawnDelayedTask)
{
using namespace std::literals;
@@ -99,6 +117,7 @@
std::execution::then([&m](...) { m.reset(); }));
EXPECT_THROW(runToStop(), sdbusplus::exception::UnhandledStop);
+ EXPECT_NO_THROW(ctx->run());
EXPECT_FALSE(ran);
}
@@ -127,5 +146,6 @@
std::execution::then([&]() { m.reset(); }));
EXPECT_THROW(runToStop(), sdbusplus::exception::UnhandledStop);
+ EXPECT_NO_THROW(ctx->run());
EXPECT_FALSE(ran);
}