From 57faaec3da0b0cea9975ec968a294cadcc2e2e6a Mon Sep 17 00:00:00 2001 From: Osama Ahmad Date: Wed, 20 May 2026 03:02:12 +0300 Subject: [PATCH] fix: skip empty benchmarks to avoid infinite loops when CODSPEED_MODE=off When `CODSPEED_MODE=off`, empty benchmark bodies (which don't run the `KeepRunning()` loop) fail to advance iteration counts. Instead of triggering a hard `BM_CHECK` failure or stalling in an infinite loop, the runner now intercepts the state and gracefully drops a meaningful error message. References: - Issue: google/benchmark#1962 - Pull Request: google/benchmark#1976 --- google_benchmark/src/benchmark_runner.cc | 7 +++++-- google_benchmark/test/skip_with_error_test.cc | 9 +++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/google_benchmark/src/benchmark_runner.cc b/google_benchmark/src/benchmark_runner.cc index 2d31cca..d8fd9ff 100644 --- a/google_benchmark/src/benchmark_runner.cc +++ b/google_benchmark/src/benchmark_runner.cc @@ -143,8 +143,11 @@ void RunInThread(const BenchmarkInstance* b, IterationCount iters, State st = b->__codspeed_root_frame__Run(iters, thread_id, &timer, manager, perf_counters_measurement, profiler_manager_, is_warmup); - BM_CHECK(st.skipped() || st.iterations() >= st.max_iterations) - << "Benchmark returned before State::KeepRunning() returned false!"; + if (!(st.skipped() || st.iterations() >= st.max_iterations)) { + st.SkipWithError( + "The benchmark didn't run, nor was it explicitly skipped. Please call " + "'SkipWithXXX` in your benchmark as appropriate."); + } { MutexLock l(manager->GetBenchmarkMutex()); internal::ThreadManager::Result& results = manager->results; diff --git a/google_benchmark/test/skip_with_error_test.cc b/google_benchmark/test/skip_with_error_test.cc index a50cc45..5f8f99a 100644 --- a/google_benchmark/test/skip_with_error_test.cc +++ b/google_benchmark/test/skip_with_error_test.cc @@ -181,6 +181,15 @@ ADD_CASES("BM_error_while_paused", {{"/1/threads:1", true, "error message"}, {"/2/threads:4", false, ""}, {"/2/threads:8", false, ""}}); +void BM_malformed(benchmark::State&) { + // NOTE: empty body wanted. No thing else. +} +BENCHMARK(BM_malformed); +ADD_CASES("BM_malformed", + {{"", true, + "The benchmark didn't run, nor was it explicitly skipped. Please " + "call 'SkipWithXXX` in your benchmark as appropriate."}}); + int main(int argc, char* argv[]) { benchmark::Initialize(&argc, argv);