diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index ce19f6f7fbca..97285daa7e90 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -13,6 +13,7 @@ Bug Fixes --------- *Changes expected to improve the state of the world and are unlikely to have negative effects* +* aggregate cluster: fixed a crash due to a TLS initialization issue. * lua: fixed crash when Lua script contains streamInfo():downstreamSslConnection(). * tls: fix detection of the upstream connection close event. diff --git a/source/extensions/clusters/aggregate/cluster.cc b/source/extensions/clusters/aggregate/cluster.cc index 958c678d0202..2042ffe866a9 100644 --- a/source/extensions/clusters/aggregate/cluster.cc +++ b/source/extensions/clusters/aggregate/cluster.cc @@ -20,7 +20,9 @@ Cluster::Cluster(const envoy::config::cluster::v3::Cluster& cluster, : Upstream::ClusterImplBase(cluster, runtime, factory_context, std::move(stats_scope), added_via_api), cluster_manager_(cluster_manager), runtime_(runtime), random_(random), - tls_(tls.allocateSlot()), clusters_(config.clusters().begin(), config.clusters().end()) {} + tls_(tls.allocateSlot()), clusters_(config.clusters().begin(), config.clusters().end()) { + tls_->set([](Event::Dispatcher&) { return nullptr; }); +} PriorityContextPtr Cluster::linearizePrioritySet(const std::function& skip_predicate) { diff --git a/test/mocks/thread_local/mocks.h b/test/mocks/thread_local/mocks.h index dc6518c5068a..b3cdd0cc5539 100644 --- a/test/mocks/thread_local/mocks.h +++ b/test/mocks/thread_local/mocks.h @@ -58,17 +58,23 @@ class MockInstance : public Instance { } // ThreadLocal::Slot - ThreadLocalObjectSharedPtr get() override { return parent_.data_[index_]; } + ThreadLocalObjectSharedPtr get() override { + EXPECT_TRUE(was_set_); + return parent_.data_[index_]; + } bool currentThreadRegistered() override { return parent_.registered_; } void runOnAllThreads(const UpdateCb& cb) override { + EXPECT_TRUE(was_set_); parent_.runOnAllThreads([cb, this]() { parent_.data_[index_] = cb(parent_.data_[index_]); }); } void runOnAllThreads(const UpdateCb& cb, Event::PostCb main_callback) override { + EXPECT_TRUE(was_set_); parent_.runOnAllThreads([cb, this]() { parent_.data_[index_] = cb(parent_.data_[index_]); }, main_callback); } void set(InitializeCb cb) override { + was_set_ = true; if (parent_.defer_data) { parent_.deferred_data_[index_] = cb; } else { @@ -78,6 +84,7 @@ class MockInstance : public Instance { MockInstance& parent_; const uint32_t index_; + bool was_set_{}; // set() must be called before other functions. }; void call() {