diff --git a/gennghttpxfun.py b/gennghttpxfun.py index 172d9f03..1f4d9b79 100755 --- a/gennghttpxfun.py +++ b/gennghttpxfun.py @@ -165,6 +165,7 @@ OPTIONS = [ "single-thread", "add-x-forwarded-proto", "strip-incoming-x-forwarded-proto", + "single-process", ] LOGVARS = [ diff --git a/src/shrpx.cc b/src/shrpx.cc index 38594155..683e7ad8 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -1205,13 +1205,17 @@ pid_t fork_worker_process(int &main_ipc_fd, return -1; } - auto pid = fork(); + auto config = get_config(); + + pid_t pid = 0; + + if (!config->single_process) { + pid = fork(); + } if (pid == 0) { ev_loop_fork(EV_DEFAULT); - auto config = get_config(); - for (auto &addr : config->conn.listener.addrs) { util::make_socket_closeonexec(addr.fd); } @@ -1230,22 +1234,37 @@ pid_t fork_worker_process(int &main_ipc_fd, LOG(FATAL) << "Unblocking all signals failed: " << xsi_strerror(error, errbuf.data(), errbuf.size()); - nghttp2_Exit(EXIT_FAILURE); + if (config->single_process) { + exit(EXIT_FAILURE); + } else { + nghttp2_Exit(EXIT_FAILURE); + } + } + + if (!config->single_process) { + close(ipc_fd[1]); } - close(ipc_fd[1]); WorkerProcessConfig wpconf{ipc_fd[0]}; rv = worker_process_event_loop(&wpconf); if (rv != 0) { LOG(FATAL) << "Worker process returned error"; - nghttp2_Exit(EXIT_FAILURE); + if (config->single_process) { + exit(EXIT_FAILURE); + } else { + nghttp2_Exit(EXIT_FAILURE); + } } LOG(NOTICE) << "Worker process shutting down momentarily"; // call exit(...) instead of nghttp2_Exit to get leak sanitizer report - nghttp2_Exit(EXIT_SUCCESS); + if (config->single_process) { + exit(EXIT_SUCCESS); + } else { + nghttp2_Exit(EXIT_SUCCESS); + } } // parent process @@ -1322,7 +1341,7 @@ int event_loop() { auto loop = ev_default_loop(config->ev_loop_flags); - int ipc_fd; + int ipc_fd = 0; auto pid = fork_worker_process(ipc_fd, {}); @@ -2641,6 +2660,14 @@ Process: --user= Run this program as . This option is intended to be used to drop root privileges. + --single-process + Run this program in a single process mode for debugging + purpose. Without this option, nghttpx creates at least + 2 processes: master and worker processes. If this + option is used, master and worker are unified into a + single process. nghttpx still spawns additional process + if neverbleed is used. In the single process mode, the + signal handling feature is disabled. Scripting: --mruby-file= @@ -3000,7 +3027,7 @@ void reload_config(WorkerProcess *wp) { // already created first default loop. auto loop = ev_default_loop(new_config->ev_loop_flags); - int ipc_fd; + int ipc_fd = 0; // fork_worker_process and forked child process assumes new // configuration can be obtained from get_config(). @@ -3309,6 +3336,7 @@ int main(int argc, char **argv) { {SHRPX_OPT_ADD_X_FORWARDED_PROTO.c_str(), no_argument, &flag, 157}, {SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_PROTO.c_str(), no_argument, &flag, 158}, + {SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159}, {nullptr, 0, nullptr, 0}}; int option_index = 0; @@ -4055,6 +4083,11 @@ int main(int argc, char **argv) { cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_PROTO, StringRef::from_lit("yes")); break; + case 159: + // --single-process + cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_PROCESS, + StringRef::from_lit("yes")); + break; default: break; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 8914a63c..6e41acb6 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -1620,6 +1620,9 @@ int option_lookup_token(const char *name, size_t namelen) { if (util::strieq_l("client-cipher", name, 13)) { return SHRPX_OPTID_CLIENT_CIPHERS; } + if (util::strieq_l("single-proces", name, 13)) { + return SHRPX_OPTID_SINGLE_PROCESS; + } break; case 't': if (util::strieq_l("tls-proto-lis", name, 13)) { @@ -3374,6 +3377,10 @@ int parse_config(Config *config, int optid, const StringRef &opt, case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_PROTO: config->http.xfp.strip_incoming = util::strieq_l("yes", optarg); + return 0; + case SHRPX_OPTID_SINGLE_PROCESS: + config->single_process = util::strieq_l("yes", optarg); + return 0; case SHRPX_OPTID_CONF: LOG(WARN) << "conf: ignored"; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index ba6f0cf2..251ece69 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -340,6 +340,7 @@ constexpr auto SHRPX_OPT_ADD_X_FORWARDED_PROTO = StringRef::from_lit("add-x-forwarded-proto"); constexpr auto SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_PROTO = StringRef::from_lit("strip-incoming-x-forwarded-proto"); +constexpr auto SHRPX_OPT_SINGLE_PROCESS = StringRef::from_lit("single-process"); constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; @@ -872,6 +873,7 @@ struct Config { verbose{false}, daemon{false}, http2_proxy{false}, + single_process{false}, single_thread{false}, ev_loop_flags{0} {} ~Config(); @@ -913,6 +915,9 @@ struct Config { bool verbose; bool daemon; bool http2_proxy; + // Run nghttpx in single process mode. With this mode, signal + // handling is omitted. + bool single_process; bool single_thread; // flags passed to ev_default_loop() and ev_loop_new() int ev_loop_flags; @@ -1049,6 +1054,7 @@ enum { SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER, SHRPX_OPTID_RLIMIT_NOFILE, SHRPX_OPTID_SERVER_NAME, + SHRPX_OPTID_SINGLE_PROCESS, SHRPX_OPTID_SINGLE_THREAD, SHRPX_OPTID_STREAM_READ_TIMEOUT, SHRPX_OPTID_STREAM_WRITE_TIMEOUT,