diff --git a/.gitea/workflows/bazel.yml b/.gitea/workflows/bazel.yml index e4dbafc..eaf62a9 100644 --- a/.gitea/workflows/bazel.yml +++ b/.gitea/workflows/bazel.yml @@ -60,13 +60,13 @@ jobs: shell: bash run: | set -o pipefail - bazel test //framework/... --test_output=errors --test_verbose_timeout_warnings 2>&1 | tee ci-test.log + bazel test -c opt --strip=always //framework/... --test_output=errors --test_verbose_timeout_warnings 2>&1 | tee ci-test.log - name: HTTP concurrency benchmark smoke test id: concurrency_benchmark shell: bash run: | set -o pipefail - bazel run //framework/tests:concurrency_benchmark -- \ + bazel run -c opt --strip=always //framework/tests:concurrency_benchmark -- \ --server-threads 2 --concurrency 8 --requests 80 --warmup 8 \ 2>&1 | tee ci-concurrency-benchmark.log - name: Publish test and benchmark summary @@ -138,5 +138,5 @@ jobs: run: | cp .bazelrc ./example cd example - bazel build app + bazel build -c opt --strip=always app cd .. diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml index 6578988..f4f3593 100644 --- a/.github/workflows/bazel.yml +++ b/.github/workflows/bazel.yml @@ -64,13 +64,13 @@ jobs: shell: bash run: | set -o pipefail - bazel test //framework/... --test_output=errors --test_verbose_timeout_warnings --verbose_failures 2>&1 | tee ci-test.log + bazel test -c opt --strip=always //framework/... --test_output=errors --test_verbose_timeout_warnings --verbose_failures 2>&1 | tee ci-test.log - name: HTTP concurrency benchmark smoke test id: concurrency_benchmark shell: bash run: | set -o pipefail - bazel run //framework/tests:concurrency_benchmark -- \ + bazel run -c opt --strip=always //framework/tests:concurrency_benchmark -- \ --server-threads 2 --concurrency 8 --requests 80 --warmup 8 \ 2>&1 | tee ci-concurrency-benchmark.log - name: Upload failed test logs @@ -161,7 +161,7 @@ jobs: set -o pipefail cp .bazelrc ./example cd example - bazel build app 2>&1 | tee ../ci-build.log + bazel build -c opt --strip=always app 2>&1 | tee ../ci-build.log - name: Upload failed example build logs if: failure() uses: actions/upload-artifact@v4 diff --git a/MODULE.bazel b/MODULE.bazel index 18f21cc..c97832b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,6 +1,6 @@ module( name = "khttpd", - version = "0.5.2", + version = "0.5.3", ) bazel_dep(name = "platforms", version = "1.1.0") diff --git a/framework/server.cpp b/framework/server.cpp index bd1dcb6..afba162 100644 --- a/framework/server.cpp +++ b/framework/server.cpp @@ -107,6 +107,12 @@ void Server::run() { IoContextPool::instance().get_io_context().run(); + // stop() only signals the pool so it can be called from an Asio worker + // without joining itself. The run() caller is the owner of the Server + // lifetime, so wait for every worker before returning and allowing Server's + // handlers, routers, and acceptor to be destroyed. + IoContextPool::instance().shutdown(); + spdlog::info("Server workers stopped."); } diff --git a/framework/tests/server_stability_test.cpp b/framework/tests/server_stability_test.cpp index 3bdb57e..2f24006 100644 --- a/framework/tests/server_stability_test.cpp +++ b/framework/tests/server_stability_test.cpp @@ -12,6 +12,7 @@ #include #include "framework/context/http_context.hpp" +#include "framework/io_context_pool.hpp" #include "framework/server.hpp" namespace beast = boost::beast; @@ -112,6 +113,10 @@ TEST(ServerStabilityTest, HandlesManyConcurrentRequests) { server_thread.join(); } + // Server::run() must not return while the process-wide pool still has + // workers executing handlers that reference the server and its routers. + EXPECT_EQ(khttpd_fw::IoContextPool::instance().get_thread_count(), 0U); + constexpr int total_requests = kThreadCount * kRequestsPerThread; EXPECT_EQ(successes.load(), total_requests); EXPECT_EQ(handled.load(), total_requests);