From 9ca4feefa7a3d76115564d24c3d686d9c09019a7 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Mon, 17 Feb 2025 16:52:03 +0800 Subject: [PATCH] testing: prevent test scheduling after reactor exit Previously, when handling "--help" (introduced in b8a13bebe4), we returned status code 0 but continued scheduling test tasks to the Seastar reactor. This caused test applications to hang since the tasks expected the exchanger 'e' to be available after reactor exit. Fix this by using the "_done" flag to track reactor state: - Set "_done" when Seastar application exits - Skip task scheduling and exchanger wait if "_done" is set - Change test_runner::start_thread() to return bool indicating successful engine startup instead of exit code (exit code now stored in _exit_code member) This fixes the regression where "--help" would cause test applications to hang indefinitely. Fixes #2635 Signed-off-by: Kefu Chai Closes scylladb/seastar#2644 --- include/seastar/testing/test_runner.hh | 2 +- src/testing/test_runner.cc | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/seastar/testing/test_runner.hh b/include/seastar/testing/test_runner.hh index 12df8180f9..cb9b777a47 100644 --- a/include/seastar/testing/test_runner.hh +++ b/include/seastar/testing/test_runner.hh @@ -46,7 +46,7 @@ private: start_thread_args(int ac_, char** av_) noexcept : ac(ac_), av(av_) {} }; std::unique_ptr _st_args; - int start_thread(int ac, char** av); + bool start_thread(int ac, char** av); public: // Returns whether initialization was successful. // Will return as soon as the seastar::app was started. diff --git a/src/testing/test_runner.cc b/src/testing/test_runner.cc index 22eb7c1a77..55ebcdb42b 100644 --- a/src/testing/test_runner.cc +++ b/src/testing/test_runner.cc @@ -63,8 +63,8 @@ test_runner::start(int ac, char** av) { return true; } -int test_runner::start_thread(int ac, char** av) { - auto init_outcome = std::make_shared>(); +bool test_runner::start_thread(int ac, char** av) { + auto init_outcome = std::make_shared>(); namespace bpo = boost::program_options; _thread = std::make_unique([this, ac, av, init_outcome]() mutable { @@ -75,7 +75,7 @@ int test_runner::start_thread(int ac, char** av) { // We guarantee that only one thread is running. // We only read this after that one thread is joined, so this is safe. _exit_code = app.run(ac, av, [this, &app, init_outcome = init_outcome.get()] { - init_outcome->give(0); + init_outcome->give(true); auto init = [&app] { auto conf_seed = app.configuration()["random-seed"]; auto seed = conf_seed.empty() ? std::random_device()(): conf_seed.as(); @@ -108,7 +108,7 @@ int test_runner::start_thread(int ac, char** av) { return 0; }); }); - init_outcome->give(_exit_code); + init_outcome->give(false); }); return init_outcome->take(); @@ -119,14 +119,14 @@ test_runner::run_sync(std::function()> task) { if (_st_args) { start_thread_args sa = *_st_args; _st_args.reset(); - if (int start_status = start_thread(sa.ac, sa.av); start_status != 0) { + if (!start_thread(sa.ac, sa.av)) { // something bad happened when starting the reactor or app, and // the _thread has exited before taking any task. but we need to // move on. let's report this bad news with exit code - _exit_code = start_status; + _done = true; } } - if (_exit_code != 0) { + if (_done) { // we failed to start the worker reactor, so we cannot send the task to // it. return;