Skip to content

Commit

Permalink
hot restart: block new starts if previous process is still initializi…
Browse files Browse the repository at this point in the history
…ng (#553)

fixes #550
  • Loading branch information
mattklein123 authored Mar 10, 2017
1 parent e49093e commit 2685331
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
23 changes: 17 additions & 6 deletions source/exe/hot_restart.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace Server {

// Increment this whenever there is a shared memory / RPC change that will prevent a hot restart
// from working. Operations code can then cope with this and do a full restart.
const uint64_t SharedMemory::VERSION = 4;
const uint64_t SharedMemory::VERSION = 5;

SharedMemory& SharedMemory::initialize(Options& options) {
int flags = O_RDWR;
Expand Down Expand Up @@ -53,6 +53,16 @@ SharedMemory& SharedMemory::initialize(Options& options) {
RELEASE_ASSERT(shmem->version_ == VERSION);
}

// Here we catch the case where a new Envoy starts up when the current Envoy has not yet fully
// initialized. The startup logic is quite compicated, and it's not worth trying to handle this
// in a finer way. This will cause the startup to fail with an error code early, without
// affecting any currently running processes. The process runner should try again later with some
// back off and with the same hot restart epoch number.
uint64_t old_flags = shmem->flags_.fetch_or(Flags::INITIALIZING);
if (old_flags & Flags::INITIALIZING) {
throw EnvoyException("previous envoy process is still initializing");
}

return *shmem;
}

Expand Down Expand Up @@ -142,13 +152,14 @@ sockaddr_un HotRestartImpl::createDomainSocketAddress(uint64_t id) {
}

void HotRestartImpl::drainParentListeners() {
if (options_.restartEpoch() == 0) {
return;
if (options_.restartEpoch() > 0) {
// No reply expected.
RpcBase rpc(RpcMessageType::DrainListenersRequest);
sendMessage(parent_address_, rpc);
}

// No reply expected.
RpcBase rpc(RpcMessageType::DrainListenersRequest);
sendMessage(parent_address_, rpc);
// At this point we are initialized and a new Envoy can startup if needed.
shmem_.flags_ &= ~SharedMemory::Flags::INITIALIZING;
}

int HotRestartImpl::duplicateParentListenSocket(uint32_t port) {
Expand Down
5 changes: 5 additions & 0 deletions source/exe/hot_restart.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ class SharedMemory {
static std::string version();

private:
struct Flags {
static const uint64_t INITIALIZING = 0x1;
};

SharedMemory() {}

/**
Expand All @@ -37,6 +41,7 @@ class SharedMemory {

uint64_t size_;
uint64_t version_;
std::atomic<uint64_t> flags_;
pthread_mutex_t log_lock_;
pthread_mutex_t access_log_lock_;
pthread_mutex_t stat_lock_;
Expand Down

0 comments on commit 2685331

Please sign in to comment.