diff --git a/source/server/BUILD b/source/server/BUILD index dc82ca7ef502a..a25a5615dc397 100644 --- a/source/server/BUILD +++ b/source/server/BUILD @@ -55,6 +55,7 @@ envoy_cc_library( "@envoy_api//envoy/config/bootstrap/v3:pkg_cc_proto", "@envoy_api//envoy/config/metrics/v3:pkg_cc_proto", "@envoy_api//envoy/config/trace/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/watchdog/abort_action/v3alpha:pkg_cc_proto", ], ) diff --git a/source/server/configuration_impl.cc b/source/server/configuration_impl.cc index 237f576c37afb..aac8cf2881780 100644 --- a/source/server/configuration_impl.cc +++ b/source/server/configuration_impl.cc @@ -10,6 +10,7 @@ #include "envoy/config/bootstrap/v3/bootstrap.pb.h" #include "envoy/config/metrics/v3/stats.pb.h" #include "envoy/config/trace/v3/http_tracer.pb.h" +#include "envoy/extensions/watchdog/abort_action/v3alpha/abort_action.pb.h" #include "envoy/network/connection.h" #include "envoy/runtime/runtime.h" #include "envoy/server/instance.h" @@ -171,7 +172,30 @@ WatchdogImpl::WatchdogImpl(const envoy::config::bootstrap::v3::Watchdog& watchdo multikill_timeout_ = std::chrono::milliseconds(PROTOBUF_GET_MS_OR_DEFAULT(watchdog, multikill_timeout, 0)); multikill_threshold_ = PROTOBUF_PERCENT_TO_DOUBLE_OR_DEFAULT(watchdog, multikill_threshold, 0.0); - actions_ = watchdog.actions(); + auto actions = watchdog.actions(); + +// Add abort_action if it's available on the given platform and killing is +// enabled since it's more helpful than the default kill action. +#ifndef WIN32 + envoy::extensions::watchdog::abort_action::v3alpha::AbortActionConfig abort_config; + // Wait one second for the aborted thread to abort. + abort_config.mutable_wait_duration()->set_seconds(1); + + if (kill_timeout > 0) { + envoy::config::bootstrap::v3::Watchdog::WatchdogAction* abort_action_config = actions.Add(); + abort_action_config->set_event(envoy::config::bootstrap::v3::Watchdog::WatchdogAction::KILL); + abort_action_config->mutable_config()->mutable_typed_config()->PackFrom(abort_config); + } + + if (multikill_timeout_.count() > 0) { + envoy::config::bootstrap::v3::Watchdog::WatchdogAction* abort_action_config = actions.Add(); + abort_action_config->set_event( + envoy::config::bootstrap::v3::Watchdog::WatchdogAction::MULTIKILL); + abort_action_config->mutable_config()->mutable_typed_config()->PackFrom(abort_config); + } +#endif + + actions_ = actions; } InitialImpl::InitialImpl(const envoy::config::bootstrap::v3::Bootstrap& bootstrap) { diff --git a/test/server/configuration_impl_test.cc b/test/server/configuration_impl_test.cc index 2681825740a98..77cca2586db7c 100644 --- a/test/server/configuration_impl_test.cc +++ b/test/server/configuration_impl_test.cc @@ -754,8 +754,8 @@ TEST_F(ConfigurationImplTest, KillTimeoutWithoutSkew) { MainImpl config; config.initialize(bootstrap, server_, cluster_manager_factory_); - EXPECT_EQ(std::chrono::milliseconds(1000), config.workerWatchdogConfig().killTimeout()); - EXPECT_EQ(std::chrono::milliseconds(1000), config.mainThreadWatchdogConfig().killTimeout()); + EXPECT_EQ(config.workerWatchdogConfig().killTimeout(), std::chrono::milliseconds(1000)); + EXPECT_EQ(config.mainThreadWatchdogConfig().killTimeout(), std::chrono::milliseconds(1000)); } TEST_F(ConfigurationImplTest, CanSkewsKillTimeout) { @@ -793,10 +793,45 @@ TEST_F(ConfigurationImplTest, DoesNotSkewIfKillTimeoutDisabled) { MainImpl config; config.initialize(bootstrap, server_, cluster_manager_factory_); - EXPECT_EQ(std::chrono::milliseconds(0), config.mainThreadWatchdogConfig().killTimeout()); - EXPECT_EQ(std::chrono::milliseconds(0), config.workerWatchdogConfig().killTimeout()); + EXPECT_EQ(config.mainThreadWatchdogConfig().killTimeout(), std::chrono::milliseconds(0)); + EXPECT_EQ(config.workerWatchdogConfig().killTimeout(), std::chrono::milliseconds(0)); } +// AbortAction not yet supported on Windows. +#ifndef WIN32 +TEST_F(ConfigurationImplTest, ShouldAddsAbortActionIfKillingIsEnabled) { + envoy::config::bootstrap::v3::Bootstrap bootstrap; + MainImpl config; + const std::string kill_json = R"EOF( + { + "watchdog": { + "kill_timeout": "1.0s", + "multikill_timeout" : "1.0s" + }, + })EOF"; + + TestUtility::loadFromJson(kill_json, bootstrap); + config.initialize(bootstrap, server_, cluster_manager_factory_); + + // We should have the abort action added to both KILL and MULTIKILL events. + EXPECT_EQ(config.workerWatchdogConfig().actions().size(), 2); + EXPECT_EQ(config.mainThreadWatchdogConfig().actions().size(), 2); +} + +TEST_F(ConfigurationImplTest, ShouldNotAddAbortActionIfKillingIsDisabled) { + envoy::config::bootstrap::v3::Bootstrap bootstrap; + MainImpl config; + const std::string killing_disabled_json = R"EOF( { "watchdog": { "miss_timeout": "1.0s" }})EOF"; + + TestUtility::loadFromJson(killing_disabled_json, bootstrap); + config.initialize(bootstrap, server_, cluster_manager_factory_); + + // We should have the abort action added + EXPECT_EQ(config.workerWatchdogConfig().actions().size(), 0); + EXPECT_EQ(config.mainThreadWatchdogConfig().actions().size(), 0); +} +#endif + TEST_F(ConfigurationImplTest, ShouldErrorIfBothWatchdogsAndWatchdogSet) { const std::string json = R"EOF( { "watchdogs": {}, "watchdog": {}})EOF";