Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e696fe1
Factor out most of the contents of main() into a new MainCommon class…
jmarantz Feb 6, 2018
d796786
Formatting fixups.
jmarantz Feb 6, 2018
622e5d2
Get all tests working with minimal changes.
jmarantz Feb 8, 2018
6a87f69
formatting fixups
jmarantz Feb 8, 2018
de78e95
streamline the validation flow.
jmarantz Feb 9, 2018
3e5e52e
Merge branch 'master' into main-common-as-class
jmarantz Feb 9, 2018
53f3ec0
mutex-protect Server::InstanceImpl::terminate_
jmarantz Feb 9, 2018
b9d284b
formatting fixups
jmarantz Feb 9, 2018
2ff4f4a
Fixes problems found after after retesting new main_common with old m…
jmarantz Feb 9, 2018
b28fa8e
fix struct/class conflict which I saw only in CI
jmarantz Feb 9, 2018
ccd38ad
add missing override.
jmarantz Feb 9, 2018
4d2bc12
Use TEST_RUNDIR rather than TEST_SRCDIR.
jmarantz Feb 9, 2018
4bd2da7
Specify envoy-standard return comment.
jmarantz Feb 9, 2018
c84e9b4
Test the legacy-main past using an old copy of main() in a test.
jmarantz Feb 9, 2018
8e0262a
formatting fixup.
jmarantz Feb 9, 2018
928deb7
Just get a writable char* out of std::string by taking a pointer to c…
jmarantz Feb 9, 2018
94e9b12
Try to get CI coverage tests passing by disabling main_common_test.
jmarantz Feb 10, 2018
1763e71
Try using #if 0 to disable a test for coverage, as ifndef ENVOY_CONFI…
jmarantz Feb 10, 2018
2ba3207
Try using #if !ENVOY_CONFIG_COVERAGE rather than #ifndef to skip this…
jmarantz Feb 10, 2018
a9237fe
Define ENVOY_CONFIG_COVERAGE as a -D flag in addition to a bazel sett…
jmarantz Feb 11, 2018
57ef61f
Fix the --cxxopt syntax.
jmarantz Feb 11, 2018
3b469a4
Raise coverage timeout to 1000s and make test output streamed.
jmarantz Feb 11, 2018
f45099c
use EXIT_SUCCESS/EXIT_FAILURE rather than 0/1 for main() return codes.
jmarantz Feb 11, 2018
552cb2a
use EXIT_SUCCESS/FAILURE in the test too.
jmarantz Feb 11, 2018
4914e62
Catch one more EXIT_xxx xform.
jmarantz Feb 11, 2018
58a0180
Remove mutex around terminate_ after convincing myself it wasn't nece…
jmarantz Feb 11, 2018
8cb20e7
Switch the new test config to yaml format.
jmarantz Feb 11, 2018
ada35db
Cleanups as suggested by mattklein123.
jmarantz Feb 11, 2018
ce29a45
Move test yaml to test/config/integration, clarify try/catch discipli…
jmarantz Feb 11, 2018
c2bb454
Move overrides into the existing group of overrides.
jmarantz Feb 11, 2018
92a9544
add missing file.
jmarantz Feb 11, 2018
22a2e80
Attempt to get main_common_test into coverage by just disabling HANDL…
jmarantz Feb 11, 2018
d1cf0b9
Revert "Attempt to get main_common_test into coverage by just disabli…
jmarantz Feb 11, 2018
6372516
Clean up argv, which is surprisingly messy.
jmarantz Feb 12, 2018
1e29195
Address comments from hutch.
jmarantz Feb 13, 2018
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
5 changes: 5 additions & 0 deletions configs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,8 @@ genrule(
":configgen",
],
)

filegroup(
name = "google_com_proxy_port_0",
srcs = ["google_com_proxy_port_0.json"],
)
48 changes: 48 additions & 0 deletions configs/google_com_proxy_port_0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best practice is to write new example configs in YAML; this the preferred human readable config representation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"listeners": [{
"address": "tcp://127.0.0.1:0",
"filters": [{
"name": "http_connection_manager",
"config": {
"codec_type": "auto",
"stat_prefix": "ingress_http",
"route_config": {
"virtual_hosts": [{
"name": "local_service",
"domains": [
"*"
],
"routes": [{
"timeout_ms": 0,
"prefix": "/",
"host_rewrite": "www.google.com",
"cluster": "service_google"
}]
}]
},
"filters": [{
"name": "router",
"config": {}
}]
}
}]
}],
"admin": {
"access_log_path": "/tmp/admin_access.log",
"address": "tcp://127.0.0.1:0"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we're using a v1 config here? In general, unless verifying v1 regression, we're trying to turn down v1 and only add new stuff as v2.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was being lazy and copied the first plausible config I found. Done.

},
"cluster_manager": {
"clusters": [{
"name": "service_google",
"connect_timeout_ms": 250,
"type": "logical_dns",
"lb_type": "round_robin",
"hosts": [{
"url": "tcp://google.com:443"
}],
"ssl_context": {
"sni": "www.google.com"
}
}]
}
}
5 changes: 4 additions & 1 deletion include/envoy/server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ envoy_cc_library(
envoy_cc_library(
name = "hot_restart_interface",
hdrs = ["hot_restart.h"],
deps = ["//include/envoy/event:dispatcher_interface"],
deps = [
"//include/envoy/event:dispatcher_interface",
"//include/envoy/thread:thread_interface",
],
)

envoy_cc_library(
Expand Down
17 changes: 17 additions & 0 deletions include/envoy/server/hot_restart.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "envoy/common/pure.h"
#include "envoy/event/dispatcher.h"
#include "envoy/stats/stats.h"
#include "envoy/thread/thread.h"

namespace Envoy {
namespace Server {
Expand Down Expand Up @@ -78,6 +80,21 @@ class HotRestart {
* perform a full or hot restart.
*/
virtual std::string version() PURE;

/**
* @return Thread::BasicLockable& a lock for logging.
*/
virtual Thread::BasicLockable& logLock() PURE;

/**
* @return Thread::BasicLockable& a lock for access logs.
*/
virtual Thread::BasicLockable& accessLogLock() PURE;

/**
* @returns an allocator for stats.
*/
virtual Stats::RawStatDataAllocator& stats_allocator() PURE;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: statsAllocator()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

};

} // namespace Server
Expand Down
24 changes: 24 additions & 0 deletions include/envoy/stats/stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,5 +281,29 @@ class StoreRoot : public Store {

typedef std::unique_ptr<StoreRoot> StoreRootPtr;

struct RawStatData;

/**
* Abstract interface for allocating a RawStatData.
*/
class RawStatDataAllocator {
public:
virtual ~RawStatDataAllocator() {}

/**
* @return RawStatData* a raw stat data block for a given stat name or nullptr if there is no more
* memory available for stats. The allocator may return a reference counted data location

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, I think s/may return/should return/. We have an outstanding issue related to this at #2453

* by name if one already exists with the same name. This is used for intra-process
* scope swapping as well as inter-process hot restart.
*/
virtual RawStatData* alloc(const std::string& name) PURE;

/**
* Free a raw stat data block. The allocator should handle reference counting and only truly
* free the block if it is no longer needed.
*/
virtual void free(RawStatData& data) PURE;
};

} // namespace Stats
} // namespace Envoy
22 changes: 0 additions & 22 deletions source/common/stats/stats_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,28 +191,6 @@ struct RawStatData {
static size_t& initializeAndGetMutableMaxObjNameLength(size_t configured_size);
};

/**
* Abstract interface for allocating a RawStatData.
*/
class RawStatDataAllocator {
public:
virtual ~RawStatDataAllocator() {}

/**
* @return RawStatData* a raw stat data block for a given stat name or nullptr if there is no more
* memory available for stats. The allocator may return a reference counted data location
* by name if one already exists with the same name. This is used for intra-process
* scope swapping as well as inter-process hot restart.
*/
virtual RawStatData* alloc(const std::string& name) PURE;

/**
* Free a raw stat data block. The allocator should handle reference counting and only truly
* free the block if it is no longer needed.
*/
virtual void free(RawStatData& data) PURE;
};

/**
* Implementation of the Metric interface. Virtual inheritance is used because the interfaces that
* will inherit from Metric will have other base classes that will also inherit from Metric.
Expand Down
12 changes: 5 additions & 7 deletions source/exe/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,9 @@ envoy_cc_library(
deps = [
":envoy_main_common_lib",
":extra_protocol_proxies_lib",
"//source/server:hot_restart_lib",
"//source/server:options_lib",
"//source/server/config/http:lightstep_lib",
"//source/server/config/http:zipkin_lib",
] + select({
"//bazel:disable_signal_trace": [],
"//conditions:default": [":sigaction_lib"],
}),
],
)

envoy_cc_library(
Expand All @@ -100,7 +95,10 @@ envoy_cc_library(
"//source/server:hot_restart_nop_lib",
"//source/server:proto_descriptors_lib",
"//source/server/config_validation:server_lib",
],
] + select({
"//bazel:disable_signal_trace": [],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test with --define signal_trace=disabled? We don't have any CI tests to catch these variants of Bazel build, so when moving things around it's probably a good idea to manually verify.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea. Doing so now. Actually, why is this a compile-time decision rather than an option? Then it would be easier to test without rebuilding the entire tree. Same with HotRestart, though that's addressed in #2568.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these options are compile-time as we want to squash dependencies (e.g. Google gRPC) or demonstrate that site-local replacement or build time removal of features is possible (e.g. we replace during import on the Google side). Hot restart is probably a better contender to be fully dynamic, as it doesn't introduce any deps.

There's a wider conversation happening right now in #2069. Basically, we need some way to provide greater build time flexibility to allow very minimal Envoy binary deployments while also support kitchen sink builds with dynamic configuration. The former might be interesting in resource constrained embedded or container environments, the latter on a traditional fat server.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't arguing against any compile-time switches, but it wasn't obvious what dependency this one had. I was thinking that if we were compiling on Windows and the APIs didn't exist, we'd just #if them out based on platform support as opposed to config, but keep the class API above that consistent.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the signal_trace deps are the Backtrace library, an external dependency.

"//conditions:default": [":sigaction_lib"],
}),
)

envoy_cc_library(
Expand Down
45 changes: 10 additions & 35 deletions source/exe/main.cc
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
#include <iostream>
#include <memory>

#include "exe/main_common.h"

#ifdef ENVOY_HANDLE_SIGNALS
#include "exe/signal_action.h"
#endif

#ifdef ENVOY_HOT_RESTART
#include "server/hot_restart_impl.h"
#endif

#include "server/options_impl.h"

#include "spdlog/spdlog.h"

// NOLINT(namespace-envoy)

/**
Expand All @@ -24,32 +9,22 @@
* deployment such as initializing signal handling. It calls main_common
* after setting up command line options.
*/
int main(int argc, char** argv) {
#ifdef ENVOY_HANDLE_SIGNALS
// Enabled by default. Control with "bazel --define=signal_trace=disabled"
Envoy::SignalAction handle_sigs;
#endif

int main(int argc, const char** argv) {
try {
#ifdef ENVOY_HOT_RESTART
// Enabled by default, except on OS X. Control with "bazel --define=hot_restart=disabled"
const Envoy::OptionsImpl::HotRestartVersionCb hot_restart_version_cb =
[](uint64_t max_num_stats, uint64_t max_stat_name_len) {
return Envoy::Server::HotRestartImpl::hotRestartVersion(max_num_stats, max_stat_name_len);
};
Envoy::MainCommon main_common(argc, argv, true);
#else
const Envoy::OptionsImpl::HotRestartVersionCb hot_restart_version_cb = [](uint64_t, uint64_t) {
return "disabled";
};
Envoy::MainCommon main_common(argc, argv, false);
#endif

std::unique_ptr<Envoy::OptionsImpl> options;
try {
options = std::make_unique<Envoy::OptionsImpl>(argc, argv, hot_restart_version_cb,
spdlog::level::info);
return main_common.run() ? 0 : 1;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EXIT_SUCCESS/EXIT_FAILURE here also?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

} catch (const Envoy::NoServingException& e) {
return 0;
} catch (const Envoy::MalformedArgvException& e) {
std::cerr << "MalformedArgvException: " << e.what() << std::endl;

@mattklein123 mattklein123 Feb 11, 2018

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reasoning behind these new catch blocks? Were these things caught elsewhere and now are caught here? My main comment is that the errors we print should be user friendly so I don't think we should print the name of the exception which the user doesn't care about. Perhaps just "Envoy startup failure: ..."?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's possible these were necessary only when I had some other problem deeper in the code, and now it's not necessary. I'll investigate & follow up.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't extra; it's just moved. It was previously on main_common.cc:92. I removed the extra printing though, and handles the case in Server::InstanceImpl::InstanceImpl where the config fails to parse, e.g. because it is empty, which is tested in hotrestart_integration_test. I guess an invalid json config could also cause this, or failing to open the log file.

I think it makes sense to handle EnvoyException in main.cc. Or, we could re-cast the exception in MainCommon's ctor as one that was already handled in main.cc. WDYT?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine either way. The main thing I would watch out for is that we don't catch exceptions when the run loop starts running. I realize that wasn't really clearly codified, and feel free to add more comments, but the idea is that we can throw and exit(1) during startup, but once the main loop starts up any exceptions which aren't explicitly handled should crash the process w/ core dump. That's the way the code works today so I would just be careful that we maintain that behavior.

return 1;
} catch (const Envoy::EnvoyException& e) {
std::cerr << "EnvoyException: " << e.what() << std::endl;
return 1;
}
return Envoy::main_common(*options);
return 0;
}
Loading