Merge branch 'nghttpx-reload'

This commit is contained in:
Tatsuhiro Tsujikawa 2016-07-31 21:03:13 +09:00
commit fb3d6f68a8
9 changed files with 569 additions and 193 deletions

View File

@ -49,6 +49,9 @@ SIGQUIT
accepting connection. After all connections are handled, nghttpx
exits.
SIGHUP
Reload configuration file given in :option:`--conf`.
SIGUSR1
Reopen log files.
@ -56,7 +59,11 @@ SIGUSR2
Fork and execute nghttpx. It will execute the binary in the same
path with same command-line arguments and environment variables.
After new process comes up, sending SIGQUIT to the original process
to perform hot swapping.
to perform hot swapping. The difference between SIGUSR2 + SIGQUIT
and SIGHUP is that former is usually used to execute new binary, and
the master process is newly spawned. On the other hand, the latter
just reloads configuration file, and the same master process
continues to exist.
.. note::

View File

@ -236,6 +236,9 @@ all existing frontend connections are done, the current process will
exit. At this point, only new nghttpx process exists and serves
incoming requests.
If you want to just reload configuration file without executing new
binary, send SIGHUP to nghttpx master process.
Re-opening log files
--------------------

File diff suppressed because it is too large Load Diff

View File

@ -60,16 +60,44 @@
namespace shrpx {
namespace {
Config *config = nullptr;
std::unique_ptr<Config> config;
} // namespace
constexpr auto SHRPX_UNIX_PATH_PREFIX = StringRef::from_lit("unix:");
const Config *get_config() { return config; }
const Config *get_config() { return config.get(); }
Config *mod_config() { return config; }
Config *mod_config() { return config.get(); }
void create_config() { config = new Config(); }
std::unique_ptr<Config> replace_config(std::unique_ptr<Config> another) {
config.swap(another);
return another;
}
void create_config() { config = make_unique<Config>(); }
Config::~Config() {
auto &upstreamconf = http2.upstream;
nghttp2_option_del(upstreamconf.option);
nghttp2_option_del(upstreamconf.alt_mode_option);
nghttp2_session_callbacks_del(upstreamconf.callbacks);
auto &downstreamconf = http2.downstream;
nghttp2_option_del(downstreamconf.option);
nghttp2_session_callbacks_del(downstreamconf.callbacks);
auto &dumpconf = http2.upstream.debug.dump;
if (dumpconf.request_header) {
fclose(dumpconf.request_header);
}
if (dumpconf.response_header) {
fclose(dumpconf.response_header);
}
}
TicketKeys::~TicketKeys() {
/* Erase keys from memory */
@ -2398,7 +2426,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
}
included_set.insert(optarg);
auto rv = load_config(optarg.c_str(), included_set);
auto rv = load_config(config, optarg.c_str(), included_set);
included_set.erase(optarg);
if (rv != 0) {
@ -2648,7 +2676,8 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return -1;
}
int load_config(const char *filename, std::set<StringRef> &include_set) {
int load_config(Config *config, const char *filename,
std::set<StringRef> &include_set) {
std::ifstream in(filename, std::ios::binary);
if (!in) {
LOG(ERROR) << "Could not open config file " << filename;
@ -2669,7 +2698,7 @@ int load_config(const char *filename, std::set<StringRef> &include_set) {
}
*eq = '\0';
if (parse_config(mod_config(), StringRef{std::begin(line), eq},
if (parse_config(config, StringRef{std::begin(line), eq},
StringRef{eq + 1, std::end(line)}, include_set) != 0) {
return -1;
}

View File

@ -706,6 +706,8 @@ struct APIConfig {
};
struct Config {
~Config();
HttpProxy downstream_http_proxy;
HttpConfig http;
Http2Config http2;
@ -717,13 +719,9 @@ struct Config {
ImmutableString conf_path;
ImmutableString user;
ImmutableString mruby_file;
char **original_argv;
char **argv;
char *cwd;
size_t num_worker;
size_t padding;
size_t rlimit_nofile;
int argc;
uid_t uid;
gid_t gid;
pid_t pid;
@ -736,6 +734,9 @@ struct Config {
const Config *get_config();
Config *mod_config();
// Replaces the current config with given |new_config|. The old config is
// returned.
std::unique_ptr<Config> replace_config(std::unique_ptr<Config> new_config);
void create_config();
// generated by gennghttpxfun.py
@ -890,10 +891,11 @@ int parse_config(Config *config, const StringRef &opt, const StringRef &optarg,
int parse_config(Config *config, int optid, const StringRef &opt,
const StringRef &optarg, std::set<StringRef> &included_set);
// Loads configurations from |filename| and stores them in statically
// allocated Config object. This function returns 0 if it succeeds, or
// -1. See parse_config() for |include_set|.
int load_config(const char *filename, std::set<StringRef> &include_set);
// Loads configurations from |filename| and stores them in |config|.
// This function returns 0 if it succeeds, or -1. See parse_config()
// for |include_set|.
int load_config(Config *config, const char *filename,
std::set<StringRef> &include_set);
// Parses header field in |optarg|. We expect header field is formed
// like "NAME: VALUE". We require that NAME is non empty string. ":"

View File

@ -114,8 +114,9 @@ constexpr auto master_proc_ign_signals = std::array<int, 1>{{SIGPIPE}};
} // namespace
namespace {
constexpr auto worker_proc_ign_signals = std::array<int, 4>{
{REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL, GRACEFUL_SHUTDOWN_SIGNAL, SIGPIPE}};
constexpr auto worker_proc_ign_signals =
std::array<int, 5>{{REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL,
GRACEFUL_SHUTDOWN_SIGNAL, RELOAD_SIGNAL, SIGPIPE}};
} // namespace
void shrpx_signal_set_master_proc_ign_handler() {

View File

@ -34,6 +34,7 @@ namespace shrpx {
constexpr int REOPEN_LOG_SIGNAL = SIGUSR1;
constexpr int EXEC_BINARY_SIGNAL = SIGUSR2;
constexpr int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT;
constexpr int RELOAD_SIGNAL = SIGHUP;
// Blocks all signals. The previous signal mask is stored into
// |oldset| if it is not nullptr. This function returns 0 if it

View File

@ -94,16 +94,14 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
}
} // namespace
// This function is meant be called from master process, hence the
// call exit(3).
std::vector<unsigned char>
set_alpn_prefs(const std::vector<std::string> &protos) {
int set_alpn_prefs(std::vector<unsigned char> &out,
const std::vector<std::string> &protos) {
size_t len = 0;
for (const auto &proto : protos) {
if (proto.size() > 255) {
LOG(FATAL) << "Too long ALPN identifier: " << proto.size();
exit(EXIT_FAILURE);
return -1;
}
len += 1 + proto.size();
@ -111,10 +109,10 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
if (len > (1 << 16) - 1) {
LOG(FATAL) << "Too long ALPN identifier list: " << len;
exit(EXIT_FAILURE);
return -1;
}
auto out = std::vector<unsigned char>(len);
out.resize(len);
auto ptr = out.data();
for (const auto &proto : protos) {
@ -123,7 +121,7 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
ptr += proto.size();
}
return out;
return 0;
}
namespace {

View File

@ -181,8 +181,8 @@ bool check_http2_requirement(SSL *ssl);
// passed to SSL_CTX_set_options().
long int create_tls_proto_mask(const std::vector<std::string> &tls_proto_list);
std::vector<unsigned char>
set_alpn_prefs(const std::vector<std::string> &protos);
int set_alpn_prefs(std::vector<unsigned char> &out,
const std::vector<std::string> &protos);
// Setups server side SSL_CTX. This function inspects get_config()
// and if upstream_no_tls is true, returns nullptr. Otherwise