This is an automated email from the ASF dual-hosted git repository. jpeach pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 693839a31e6e3839146f4d8aa80cd0a237a51db3 Author: James Peach <[email protected]> AuthorDate: Wed May 17 21:58:15 2017 -0700 Improve graceful shutdown. Rather than sleeping in a signal handler, unify the signal handling so that we always bounce the actual work up to the SignalContinuation. Once we are there, then we can send a timed event to shutdown after the timeot, or just cause a normal shutdown immediately. On the exit path, stop the ProcessManager to keep the integration tests happy. --- proxy/Main.cc | 111 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/proxy/Main.cc b/proxy/Main.cc index 4242c6e..7512bfe 100644 --- a/proxy/Main.cc +++ b/proxy/Main.cc @@ -169,10 +169,7 @@ static int cmd_line_dprintf_level = 0; // default debug output level from ink_d static int poll_timeout = -1; // No value set. static int cmd_disable_freelist = 0; -static int shutdown_timeout = 0; - -static volatile bool sigusr1_received = false; -static volatile bool sigusr2_received = false; +static volatile bool signal_received[NSIG]; // 1: delay listen, wait for cache. // 0: Do not delay, start listen ASAP. @@ -218,14 +215,25 @@ static ArgumentDescription argument_descriptions[] = { {"accept_mss", '-', "MSS for client connections", "I", &accept_mss, nullptr, nullptr}, {"poll_timeout", 't', "poll timeout in milliseconds", "I", &poll_timeout, nullptr, nullptr}, HELP_ARGUMENT_DESCRIPTION(), - VERSION_ARGUMENT_DESCRIPTION()}; + VERSION_ARGUMENT_DESCRIPTION(), +}; + +struct AutoStopCont : public Continuation { + int + mainEvent(int /* event */, Event * /* e */) + { + pmgmt->stop(); + shutdown_event_system = true; + delete this; + return EVENT_CONT; + } + + AutoStopCont() : Continuation(new_ProxyMutex()) { SET_HANDLER(&AutoStopCont::mainEvent); } +}; class SignalContinuation : public Continuation { public: - char *end; - char *snap; - SignalContinuation() : Continuation(new_ProxyMutex()) { end = snap = nullptr; @@ -235,36 +243,59 @@ public: int periodic(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */) { - if (sigusr1_received) { - sigusr1_received = false; + if (signal_received[SIGUSR1]) { + signal_received[SIGUSR1] = false; // TODO: TS-567 Integrate with debugging allocators "dump" features? ink_freelists_dump(stderr); ResourceTracker::dump(stderr); + if (!end) { end = (char *)sbrk(0); } + if (!snap) { snap = (char *)sbrk(0); } + char *now = (char *)sbrk(0); - // TODO: Use logging instead directly writing to stderr - // This is not error condition at the first place - // so why stderr? - // - fprintf(stderr, "sbrk 0x%" PRIu64 " from first %" PRIu64 " from last %" PRIu64 "\n", (uint64_t)((ptrdiff_t)now), - (uint64_t)((ptrdiff_t)(now - end)), (uint64_t)((ptrdiff_t)(now - snap))); + Note("sbrk 0x%" PRIu64 " from first %" PRIu64 " from last %" PRIu64 "\n", (uint64_t)((ptrdiff_t)now), + (uint64_t)((ptrdiff_t)(now - end)), (uint64_t)((ptrdiff_t)(now - snap))); snap = now; - } else if (sigusr2_received) { - sigusr2_received = false; + } + + if (signal_received[SIGUSR2]) { + signal_received[SIGUSR2] = false; + Debug("log", "received SIGUSR2, reloading traffic.out"); + // reload output logfile (file is usually called traffic.out) diags->set_stdout_output(bind_stdout); diags->set_stderr_output(bind_stderr); } + if (signal_received[SIGTERM]) { + signal_received[SIGTERM] = false; + + RecInt timeout = 0; + REC_ReadConfigInteger(timeout, "proxy.config.stop.shutdown_timeout"); + + if (timeout) { + http2_drain = true; + } + + Debug("server", "received SIGTERM, shutting down in %" PRId64 "secs", timeout); + + // Shutdown in `timeout` seconds (or now if that is 0). + eventProcessor.schedule_in(new AutoStopCont(), HRTIME_SECONDS(timeout)); + } + return EVENT_CONT; } + +private: + const char *end; + const char *snap; }; class TrackerContinuation : public Continuation @@ -431,14 +462,16 @@ init_memory_tracker(const char *config_var, RecDataT /* type ATS_UNUSED */, RecD static void proxy_signal_handler(int signo, siginfo_t *info, void *ctx) { + if ((unsigned)signo < countof(signal_received)) { + signal_received[signo] = true; + } + + // These signals are all handled by SignalContinuation. switch (signo) { case SIGUSR1: - sigusr1_received = true; - return; case SIGUSR2: - sigusr2_received = true; - return; case SIGHUP: + case SIGTERM: return; } @@ -459,14 +492,6 @@ proxy_signal_handler(int signo, siginfo_t *info, void *ctx) if (signal_is_crash(signo)) { signal_crash_handler(signo, info, ctx); } - - if (shutdown_timeout) { - http2_drain = true; - sleep(shutdown_timeout); - } - - shutdown_event_system = true; - sleep(1); } // @@ -1287,26 +1312,6 @@ init_http_header() hpack_huffman_init(); } -struct AutoStopCont : public Continuation { - int - mainEvent(int event, Event *e) - { - (void)event; - (void)e; - ::exit(0); - return 0; - } - AutoStopCont() : Continuation(new_ProxyMutex()) { SET_HANDLER(&AutoStopCont::mainEvent); } -}; - -static void -run_AutoStop() -{ - if (getenv("PROXY_AUTO_EXIT")) { - eventProcessor.schedule_in(new AutoStopCont(), HRTIME_SECONDS(atoi(getenv("PROXY_AUTO_EXIT")))); - } -} - #if TS_HAS_TESTS struct RegressionCont : public Continuation { int initialized; @@ -1687,8 +1692,6 @@ main(int /* argc ATS_UNUSED */, const char **argv) ::exit(0); } - REC_ReadConfigInteger(shutdown_timeout, "proxy.config.stop.shutdown_timeout"); - // We need to do this early so we can initialize the Machine // singleton, which depends on configuration values loaded in this. // We want to initialize Machine as early as possible because it @@ -1945,7 +1948,9 @@ main(int /* argc ATS_UNUSED */, const char **argv) run_RegressionTest(); #endif - run_AutoStop(); + if (getenv("PROXY_AUTO_EXIT")) { + eventProcessor.schedule_in(new AutoStopCont(), HRTIME_SECONDS(atoi(getenv("PROXY_AUTO_EXIT")))); + } } #if !TS_USE_POSIX_CAP -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
