Merge branch 'nghttpx-reload'
This commit is contained in:
commit
fb3d6f68a8
|
@ -49,6 +49,9 @@ SIGQUIT
|
||||||
accepting connection. After all connections are handled, nghttpx
|
accepting connection. After all connections are handled, nghttpx
|
||||||
exits.
|
exits.
|
||||||
|
|
||||||
|
SIGHUP
|
||||||
|
Reload configuration file given in :option:`--conf`.
|
||||||
|
|
||||||
SIGUSR1
|
SIGUSR1
|
||||||
Reopen log files.
|
Reopen log files.
|
||||||
|
|
||||||
|
@ -56,7 +59,11 @@ SIGUSR2
|
||||||
Fork and execute nghttpx. It will execute the binary in the same
|
Fork and execute nghttpx. It will execute the binary in the same
|
||||||
path with same command-line arguments and environment variables.
|
path with same command-line arguments and environment variables.
|
||||||
After new process comes up, sending SIGQUIT to the original process
|
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::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -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
|
exit. At this point, only new nghttpx process exists and serves
|
||||||
incoming requests.
|
incoming requests.
|
||||||
|
|
||||||
|
If you want to just reload configuration file without executing new
|
||||||
|
binary, send SIGHUP to nghttpx master process.
|
||||||
|
|
||||||
Re-opening log files
|
Re-opening log files
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
|
659
src/shrpx.cc
659
src/shrpx.cc
File diff suppressed because it is too large
Load Diff
|
@ -60,16 +60,44 @@
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
Config *config = nullptr;
|
std::unique_ptr<Config> config;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
constexpr auto SHRPX_UNIX_PATH_PREFIX = StringRef::from_lit("unix:");
|
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() {
|
TicketKeys::~TicketKeys() {
|
||||||
/* Erase keys from memory */
|
/* Erase keys from memory */
|
||||||
|
@ -2398,7 +2426,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
}
|
}
|
||||||
|
|
||||||
included_set.insert(optarg);
|
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);
|
included_set.erase(optarg);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
@ -2648,7 +2676,8 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
return -1;
|
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);
|
std::ifstream in(filename, std::ios::binary);
|
||||||
if (!in) {
|
if (!in) {
|
||||||
LOG(ERROR) << "Could not open config file " << filename;
|
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';
|
*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) {
|
StringRef{eq + 1, std::end(line)}, include_set) != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -706,6 +706,8 @@ struct APIConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
|
~Config();
|
||||||
|
|
||||||
HttpProxy downstream_http_proxy;
|
HttpProxy downstream_http_proxy;
|
||||||
HttpConfig http;
|
HttpConfig http;
|
||||||
Http2Config http2;
|
Http2Config http2;
|
||||||
|
@ -717,13 +719,9 @@ struct Config {
|
||||||
ImmutableString conf_path;
|
ImmutableString conf_path;
|
||||||
ImmutableString user;
|
ImmutableString user;
|
||||||
ImmutableString mruby_file;
|
ImmutableString mruby_file;
|
||||||
char **original_argv;
|
|
||||||
char **argv;
|
|
||||||
char *cwd;
|
|
||||||
size_t num_worker;
|
size_t num_worker;
|
||||||
size_t padding;
|
size_t padding;
|
||||||
size_t rlimit_nofile;
|
size_t rlimit_nofile;
|
||||||
int argc;
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
@ -736,6 +734,9 @@ struct Config {
|
||||||
|
|
||||||
const Config *get_config();
|
const Config *get_config();
|
||||||
Config *mod_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();
|
void create_config();
|
||||||
|
|
||||||
// generated by gennghttpxfun.py
|
// 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,
|
int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
const StringRef &optarg, std::set<StringRef> &included_set);
|
const StringRef &optarg, std::set<StringRef> &included_set);
|
||||||
|
|
||||||
// Loads configurations from |filename| and stores them in statically
|
// Loads configurations from |filename| and stores them in |config|.
|
||||||
// allocated Config object. This function returns 0 if it succeeds, or
|
// This function returns 0 if it succeeds, or -1. See parse_config()
|
||||||
// -1. See parse_config() for |include_set|.
|
// for |include_set|.
|
||||||
int load_config(const char *filename, std::set<StringRef> &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
|
// Parses header field in |optarg|. We expect header field is formed
|
||||||
// like "NAME: VALUE". We require that NAME is non empty string. ":"
|
// like "NAME: VALUE". We require that NAME is non empty string. ":"
|
||||||
|
|
|
@ -114,8 +114,9 @@ constexpr auto master_proc_ign_signals = std::array<int, 1>{{SIGPIPE}};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr auto worker_proc_ign_signals = std::array<int, 4>{
|
constexpr auto worker_proc_ign_signals =
|
||||||
{REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL, GRACEFUL_SHUTDOWN_SIGNAL, SIGPIPE}};
|
std::array<int, 5>{{REOPEN_LOG_SIGNAL, EXEC_BINARY_SIGNAL,
|
||||||
|
GRACEFUL_SHUTDOWN_SIGNAL, RELOAD_SIGNAL, SIGPIPE}};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void shrpx_signal_set_master_proc_ign_handler() {
|
void shrpx_signal_set_master_proc_ign_handler() {
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace shrpx {
|
||||||
constexpr int REOPEN_LOG_SIGNAL = SIGUSR1;
|
constexpr int REOPEN_LOG_SIGNAL = SIGUSR1;
|
||||||
constexpr int EXEC_BINARY_SIGNAL = SIGUSR2;
|
constexpr int EXEC_BINARY_SIGNAL = SIGUSR2;
|
||||||
constexpr int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT;
|
constexpr int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT;
|
||||||
|
constexpr int RELOAD_SIGNAL = SIGHUP;
|
||||||
|
|
||||||
// Blocks all signals. The previous signal mask is stored into
|
// Blocks all signals. The previous signal mask is stored into
|
||||||
// |oldset| if it is not nullptr. This function returns 0 if it
|
// |oldset| if it is not nullptr. This function returns 0 if it
|
||||||
|
|
|
@ -94,16 +94,14 @@ int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// This function is meant be called from master process, hence the
|
int set_alpn_prefs(std::vector<unsigned char> &out,
|
||||||
// call exit(3).
|
const std::vector<std::string> &protos) {
|
||||||
std::vector<unsigned char>
|
|
||||||
set_alpn_prefs(const std::vector<std::string> &protos) {
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
for (const auto &proto : protos) {
|
for (const auto &proto : protos) {
|
||||||
if (proto.size() > 255) {
|
if (proto.size() > 255) {
|
||||||
LOG(FATAL) << "Too long ALPN identifier: " << proto.size();
|
LOG(FATAL) << "Too long ALPN identifier: " << proto.size();
|
||||||
exit(EXIT_FAILURE);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
len += 1 + proto.size();
|
len += 1 + proto.size();
|
||||||
|
@ -111,10 +109,10 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
|
||||||
|
|
||||||
if (len > (1 << 16) - 1) {
|
if (len > (1 << 16) - 1) {
|
||||||
LOG(FATAL) << "Too long ALPN identifier list: " << len;
|
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();
|
auto ptr = out.data();
|
||||||
|
|
||||||
for (const auto &proto : protos) {
|
for (const auto &proto : protos) {
|
||||||
|
@ -123,7 +121,7 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
|
||||||
ptr += proto.size();
|
ptr += proto.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -181,8 +181,8 @@ bool check_http2_requirement(SSL *ssl);
|
||||||
// passed to SSL_CTX_set_options().
|
// passed to SSL_CTX_set_options().
|
||||||
long int create_tls_proto_mask(const std::vector<std::string> &tls_proto_list);
|
long int create_tls_proto_mask(const std::vector<std::string> &tls_proto_list);
|
||||||
|
|
||||||
std::vector<unsigned char>
|
int set_alpn_prefs(std::vector<unsigned char> &out,
|
||||||
set_alpn_prefs(const std::vector<std::string> &protos);
|
const std::vector<std::string> &protos);
|
||||||
|
|
||||||
// Setups server side SSL_CTX. This function inspects get_config()
|
// Setups server side SSL_CTX. This function inspects get_config()
|
||||||
// and if upstream_no_tls is true, returns nullptr. Otherwise
|
// and if upstream_no_tls is true, returns nullptr. Otherwise
|
||||||
|
|
Loading…
Reference in New Issue