Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: add a post init lifecycle stage #8217

Merged
merged 3 commits into from
Sep 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/root/intro/version_history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Version history
* router check tool: add comprehensive coverage reporting.
* router check tool: add deprecated field check.
* router check tool: add flag for only printing results of failed tests.
* server: added a post initialization lifecycle event, in addition to the existing startup and shutdown events.
* thrift_proxy: fix crashing bug on invalid transport/protocol framing
* tls: added verification of IP address SAN fields in certificates against configured SANs in the
* tracing: added support to the Zipkin reporter for sending list of spans as Zipkin JSON v2 and protobuf message over HTTP.
Expand Down
5 changes: 5 additions & 0 deletions include/envoy/server/lifecycle_notifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ class ServerLifecycleNotifier {
*/
Startup,

/**
* The server instance init manager has finished initialization.
*/
PostInit,

/**
* The server instance is being shutdown and the dispatcher is about to exit.
* This provides listeners a last chance to run a callback on the main dispatcher.
Expand Down
14 changes: 8 additions & 6 deletions source/server/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,10 @@ void InstanceImpl::loadServerFlags(const absl::optional<std::string>& flags_path
RunHelper::RunHelper(Instance& instance, const Options& options, Event::Dispatcher& dispatcher,
Upstream::ClusterManager& cm, AccessLog::AccessLogManager& access_log_manager,
Init::Manager& init_manager, OverloadManager& overload_manager,
std::function<void()> workers_start_cb)
: init_watcher_("RunHelper", [&instance, workers_start_cb]() {
std::function<void()> post_init_cb)
: init_watcher_("RunHelper", [&instance, post_init_cb]() {
if (!instance.isShutdown()) {
workers_start_cb();
post_init_cb();
}
}) {
// Setup signals.
Expand Down Expand Up @@ -522,9 +522,11 @@ RunHelper::RunHelper(Instance& instance, const Options& options, Event::Dispatch
void InstanceImpl::run() {
// RunHelper exists primarily to facilitate testing of how we respond to early shutdown during
// startup (see RunHelperTest in server_test.cc).
const auto run_helper =
RunHelper(*this, options_, *dispatcher_, clusterManager(), access_log_manager_, init_manager_,
overloadManager(), [this] { startWorkers(); });
const auto run_helper = RunHelper(*this, options_, *dispatcher_, clusterManager(),
access_log_manager_, init_manager_, overloadManager(), [this] {
notifyCallbacksForStage(Stage::PostInit);
startWorkers();
});

// Run the main dispatch loop waiting to exit.
ENVOY_LOG(info, "starting main dispatch loop");
Expand Down
28 changes: 21 additions & 7 deletions test/server/server_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,21 +219,26 @@ class ServerInstanceImplTestBase {
Thread::ThreadPtr startTestServer(const std::string& bootstrap_path,
const bool use_intializing_instance) {
absl::Notification started;
absl::Notification post_init;

auto server_thread = Thread::threadFactoryForTest().createThread([&] {
initialize(bootstrap_path, use_intializing_instance);
auto startup_handle = server_->registerCallback(ServerLifecycleNotifier::Stage::Startup,
[&] { started.Notify(); });
auto post_init_handle = server_->registerCallback(ServerLifecycleNotifier::Stage::PostInit,
[&] { post_init.Notify(); });
auto shutdown_handle = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit,
[&](Event::PostCb) { FAIL(); });
shutdown_handle = nullptr; // unregister callback
server_->run();
startup_handle = nullptr;
post_init_handle = nullptr;
server_ = nullptr;
thread_local_ = nullptr;
});

started.WaitForNotification();
post_init.WaitForNotification();
return server_thread;
}

Expand Down Expand Up @@ -321,8 +326,8 @@ TEST_P(ServerInstanceImplTest, EmptyShutdownLifecycleNotifications) {
}

TEST_P(ServerInstanceImplTest, LifecycleNotifications) {
bool startup = false, shutdown = false, shutdown_with_completion = false;
absl::Notification started, shutdown_begin, completion_block, completion_done;
bool startup = false, post_init = false, shutdown = false, shutdown_with_completion = false;
absl::Notification started, post_init_fired, shutdown_begin, completion_block, completion_done;

// Run the server in a separate thread so we can test different lifecycle stages.
auto server_thread = Thread::threadFactoryForTest().createThread([&] {
Expand All @@ -331,28 +336,33 @@ TEST_P(ServerInstanceImplTest, LifecycleNotifications) {
startup = true;
started.Notify();
});
auto handle2 = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit, [&] {
auto handle2 = server_->registerCallback(ServerLifecycleNotifier::Stage::PostInit, [&] {
post_init = true;
post_init_fired.Notify();
});
auto handle3 = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit, [&] {
shutdown = true;
shutdown_begin.Notify();
});
auto handle3 = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit,
auto handle4 = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit,
[&](Event::PostCb completion_cb) {
// Block till we're told to complete
completion_block.WaitForNotification();
shutdown_with_completion = true;
server_->dispatcher().post(completion_cb);
completion_done.Notify();
});
auto handle4 =
auto handle5 =
server_->registerCallback(ServerLifecycleNotifier::Stage::Startup, [&] { FAIL(); });
handle4 = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit,
handle5 = server_->registerCallback(ServerLifecycleNotifier::Stage::ShutdownExit,
[&](Event::PostCb) { FAIL(); });
handle4 = nullptr;
handle5 = nullptr;

server_->run();
handle1 = nullptr;
handle2 = nullptr;
handle3 = nullptr;
handle4 = nullptr;
server_ = nullptr;
thread_local_ = nullptr;
});
Expand All @@ -361,6 +371,10 @@ TEST_P(ServerInstanceImplTest, LifecycleNotifications) {
EXPECT_TRUE(startup);
EXPECT_FALSE(shutdown);

post_init_fired.WaitForNotification();
EXPECT_TRUE(post_init);
EXPECT_FALSE(shutdown);

server_->dispatcher().post([&] { server_->shutdown(); });
shutdown_begin.WaitForNotification();
EXPECT_TRUE(shutdown);
Expand Down