diff --git a/configure.ac b/configure.ac index 2c5c5187159..1c214883421 100644 --- a/configure.ac +++ b/configure.ac @@ -176,15 +176,13 @@ AC_ARG_ENABLE([mime-sanity-check], AC_MSG_RESULT([$enable_mime_sanity_check]) # Enable code coverage instrumentation only if requested by the user. -use_gcov=0 AC_MSG_CHECKING([whether to code coverage]) AC_ARG_ENABLE([coverage], [AS_HELP_STRING([--enable-coverage],[generate code coverage instrumentation])], - [use_gcov=1], + [], [enable_coverage=no] ) AC_MSG_RESULT([$enable_coverage]) -AC_SUBST(use_gcov) # # Enable -Werror. We want this enabled by default for developers, but disabled by default diff --git a/doc/appendices/command-line/traffic_server.en.rst b/doc/appendices/command-line/traffic_server.en.rst index 43c0c3c14d8..077ba97468f 100644 --- a/doc/appendices/command-line/traffic_server.en.rst +++ b/doc/appendices/command-line/traffic_server.en.rst @@ -97,4 +97,26 @@ Environment .. envvar:: PROXY_REMOTE_MGMT +This environment variable forces :program:`traffic_server` to believe that it is being managed by +:program:`traffic_manager`. + .. envvar:: PROXY_AUTO_EXIT + +When this environment variable is set to an integral number of +seconds, :program:`traffic_server` will exit that many seconds after +startup. This is primarily useful for testing. + +Signals +======= + +On `SIGTERM`, :program:`traffic_server` exits. + +On `SIGUSR1`, :program:`traffic_server` logs its current memory usage. + +On `SIGUSR2`, :program:`traffic_server` re-opens its standard error and standard out file descriptors. + +See also +======== + +:manpage:`traffic_ctl(8)`, +:manpage:`traffic_manager(8)` diff --git a/lib/ts/ink_config.h.in b/lib/ts/ink_config.h.in index ec58faa77f2..79b2c00c395 100644 --- a/lib/ts/ink_config.h.in +++ b/lib/ts/ink_config.h.in @@ -58,7 +58,6 @@ #define TS_HAS_IN6_IS_ADDR_UNSPECIFIED @has_in6_is_addr_unspecified@ #define TS_HAS_BACKTRACE @has_backtrace@ #define TS_HAS_PROFILER @has_profiler@ -#define TS_USE_GCOV @use_gcov@ #define TS_USE_FAST_SDK @use_fast_sdk@ #define TS_USE_DIAGS @use_diags@ #define TS_USE_EPOLL @use_epoll@ diff --git a/lib/ts/ink_thread.h b/lib/ts/ink_thread.h index a5baffd90cc..501170f5599 100644 --- a/lib/ts/ink_thread.h +++ b/lib/ts/ink_thread.h @@ -213,6 +213,12 @@ ink_thread_sigsetmask(int how, const sigset_t *set, sigset_t *oset) return (pthread_sigmask(how, set, oset)); } +static inline int +ink_thread_kill(ink_thread t, int sig) +{ + return pthread_kill(t, sig); +} + /******************************************************************* * Posix Semaphores ******************************************************************/ diff --git a/mgmt/BaseManager.cc b/mgmt/BaseManager.cc index 25eede84e6c..7dab2aac880 100644 --- a/mgmt/BaseManager.cc +++ b/mgmt/BaseManager.cc @@ -145,7 +145,8 @@ BaseManager::signalMgmtEntity(int msg_id, char *data_raw, int data_len) mh->msg_id = msg_id; mh->data_len = 0; } - ink_assert(enqueue(mgmt_event_queue, mh)); + + ink_release_assert(enqueue(mgmt_event_queue, mh)); return msg_id; } /* End BaseManager::signalMgmtEntity */ diff --git a/mgmt/ProcessManager.cc b/mgmt/ProcessManager.cc index 128711f5f0d..663f2067ad5 100644 --- a/mgmt/ProcessManager.cc +++ b/mgmt/ProcessManager.cc @@ -36,19 +36,112 @@ */ inkcoreapi ProcessManager *pmgmt = nullptr; +// read_management_message attempts to read a message from the management +// socket. Returns -errno on error, otherwise 0. If a message was read the +// *msg pointer will be filled in with the message that was read. +static int +read_management_message(int sockfd, ink_hrtime timeout, MgmtMessageHdr **msg) +{ + MgmtMessageHdr hdr; + int ret; + + *msg = nullptr; + + switch (mgmt_read_timeout(sockfd, ink_hrtime_to_sec(timeout), 0 /* usec */)) { + case 0: + // Timed out. + return 0; + case -1: + return -errno; + } + + // We have a message, try to read the message header. + ret = mgmt_read_pipe(sockfd, reinterpret_cast(&hdr), sizeof(MgmtMessageHdr)); + switch (ret) { + case 0: + // Received EOF. + return 0; + case sizeof(MgmtMessageHdr): + break; + default: + // Received -errno. + return ret; + } + + size_t msg_size = sizeof(MgmtMessageHdr) + hdr.data_len; + MgmtMessageHdr *full_msg = (MgmtMessageHdr *)ats_malloc(msg_size); + + memcpy(full_msg, &hdr, sizeof(MgmtMessageHdr)); + char *data_raw = reinterpret_cast(full_msg) + sizeof(MgmtMessageHdr); + + ret = mgmt_read_pipe(sockfd, data_raw, hdr.data_len); + if (ret == 0) { + // Received EOF. + ats_free(full_msg); + return 0; + } else if (ret < 0) { + // Received -errno. + ats_free(full_msg); + return ret; + } else { + ink_release_assert(ret == hdr.data_len); + // Received the message. + *msg = full_msg; + return 0; + } +} + +void +ProcessManager::start(std::function const &cb) +{ + Debug("pmgmt", "starting process manager"); + + init = cb; + + ink_release_assert(running == 0); + ink_atomic_increment(&running, 1); + poll_thread = ink_thread_create(processManagerThread, NULL, 0, 0, NULL); +} + +void +ProcessManager::stop() +{ + Debug("pmgmt", "stopping process manager"); + + ink_release_assert(running == 1); + ink_atomic_decrement(&running, 1); + + int tmp = local_manager_sockfd; + + local_manager_sockfd = -1; + close_socket(tmp); + ink_thread_kill(poll_thread, SIGINT); + + ink_thread_join(poll_thread); + poll_thread = ink_thread_null(); + + while (!queue_is_empty(mgmt_signal_queue)) { + char *sig = (char *)dequeue(mgmt_signal_queue); + ats_free(sig); + } + + ats_free(mgmt_signal_queue); +} + /* - * startProcessManager(...) + * processManagerThread(...) * The start function and thread loop for the process manager. */ void * -startProcessManager(void *arg) +ProcessManager::processManagerThread(void *arg) { void *ret = arg; while (!pmgmt) { /* Avert race condition, thread spun during constructor */ - Debug("pmgmt", "[startProcessManager] Waiting for initialization of object..."); + Debug("pmgmt", "waiting for initialization"); mgmt_sleep_sec(1); } + if (pmgmt->require_lm) { /* Allow p. process to run w/o a lm */ pmgmt->initLMConnection(); } @@ -57,22 +150,36 @@ startProcessManager(void *arg) pmgmt->init(); } - for (;;) { - if (unlikely(shutdown_event_system == true)) { - return nullptr; - } + // Start pumping messages between the local process and the process + // manager. This will terminate when the process manager terminates + // or the local process calls stop(). In either case, it is likely + // that we will first notice because we got a socket error, but in + // the latter case, the `running` flag has already been toggled so + // we know that we are really doing a shutdown. + while (pmgmt->running) { + int ret; + if (pmgmt->require_lm) { - pmgmt->pollLMConnection(); + ret = pmgmt->pollLMConnection(); + if (ret < 0 && pmgmt->running) { + Alert("exiting with read error from process manager: %s", strerror(-ret)); + } } + pmgmt->processEventQueue(); - pmgmt->processSignalQueue(); + ret = pmgmt->processSignalQueue(); + if (ret < 0 && pmgmt->running) { + Alert("exiting with write error from process manager: %s", strerror(-ret)); + } + mgmt_sleep_sec(pmgmt->timeout); } + return ret; -} /* End startProcessManager */ +} ProcessManager::ProcessManager(bool rlm) - : BaseManager(), require_lm(rlm), local_manager_sockfd(0), cbtable(nullptr), max_msgs_in_a_row(1) + : BaseManager(), require_lm(rlm), pid(getpid()), local_manager_sockfd(0), cbtable(nullptr), max_msgs_in_a_row(1) { mgmt_signal_queue = create_queue(); @@ -80,19 +187,25 @@ ProcessManager::ProcessManager(bool rlm) // Making the process_manager thread a spinning thread to start traffic server // as quickly as possible. Will reset this timeout when reconfigure() timeout = 0; - pid = getpid(); -} /* End ProcessManager::ProcessManager */ +} + +ProcessManager::~ProcessManager() +{ + if (running) { + stop(); + } +} void ProcessManager::reconfigure() { - bool found; max_msgs_in_a_row = MAX_MSGS_IN_A_ROW; - timeout = REC_readInteger("proxy.config.process_manager.timeout", &found); - ink_assert(found); - return; -} /* End ProcessManager::reconfigure */ + if (RecGetRecordInt("proxy.config.process_manager.timeout", &timeout) != REC_ERR_OKAY) { + // Default to 5sec if the timeout is unspecified. + timeout = 5; + } +} void ProcessManager::signalConfigFileChild(const char *parent, const char *child, unsigned int options) @@ -100,8 +213,9 @@ ProcessManager::signalConfigFileChild(const char *parent, const char *child, uns static const MgmtMarshallType fields[] = {MGMT_MARSHALL_STRING, MGMT_MARSHALL_STRING, MGMT_MARSHALL_INT}; MgmtMarshallInt mgmtopt = options; - size_t len = mgmt_message_length(fields, countof(fields), &parent, &child, &mgmtopt); - void *buffer = ats_malloc(len); + + size_t len = mgmt_message_length(fields, countof(fields), &parent, &child, &mgmtopt); + void *buffer = ats_malloc(len); mgmt_message_marshall(buffer, len, fields, countof(fields), &parent, &child, &mgmtopt); signalManager(MGMT_SIGNAL_CONFIG_FILE_CHILD, (const char *)buffer, len); @@ -113,8 +227,7 @@ void ProcessManager::signalManager(int msg_id, const char *data_str) { signalManager(msg_id, data_str, strlen(data_str) + 1); - return; -} /* End ProcessManager::signalManager */ +} void ProcessManager::signalManager(int msg_id, const char *data_raw, int data_len) @@ -125,10 +238,9 @@ ProcessManager::signalManager(int msg_id, const char *data_raw, int data_len) mh->msg_id = msg_id; mh->data_len = data_len; memcpy((char *)mh + sizeof(MgmtMessageHdr), data_raw, data_len); - ink_assert(enqueue(mgmt_signal_queue, mh)); - return; -} /* End ProcessManager::signalManager */ + ink_release_assert(enqueue(mgmt_signal_queue, mh)); +} bool ProcessManager::processEventQueue() @@ -138,42 +250,45 @@ ProcessManager::processEventQueue() while (!queue_is_empty(mgmt_event_queue)) { MgmtMessageHdr *mh = (MgmtMessageHdr *)dequeue(mgmt_event_queue); - Debug("pmgmt", "[ProcessManager] ==> Processing event id '%d' payload=%d", mh->msg_id, mh->data_len); + Debug("pmgmt", "processing event id '%d' payload=%d", mh->msg_id, mh->data_len); if (mh->data_len > 0) { executeMgmtCallback(mh->msg_id, (char *)mh + sizeof(MgmtMessageHdr), mh->data_len); } else { executeMgmtCallback(mh->msg_id, nullptr, 0); } + + // A shutdown message is a normal exit, so Alert rather than Fatal. if (mh->msg_id == MGMT_EVENT_SHUTDOWN) { - mgmt_fatal(0, "[ProcessManager::processEventQueue] Shutdown msg received, exiting\n"); - } /* Exit on shutdown */ + Alert("exiting on shutdown message"); + } + ats_free(mh); ret = true; } + return ret; -} /* End ProcessManager::processEventQueue */ +} -bool +int ProcessManager::processSignalQueue() { - bool ret = false; - while (!queue_is_empty(mgmt_signal_queue)) { MgmtMessageHdr *mh = (MgmtMessageHdr *)dequeue(mgmt_signal_queue); - Debug("pmgmt", "[ProcessManager] ==> Signalling local manager '%d'", mh->msg_id); + Debug("pmgmt", "signaling local manager with message ID %d", mh->msg_id); - if (require_lm && mgmt_write_pipe(local_manager_sockfd, (char *)mh, sizeof(MgmtMessageHdr) + mh->data_len) <= 0) { - mgmt_fatal(errno, "[ProcessManager::processSignalQueue] Error writing message!"); - // ink_assert(enqueue(mgmt_signal_queue, mh)); - } else { + if (require_lm) { + int ret = mgmt_write_pipe(local_manager_sockfd, (char *)mh, sizeof(MgmtMessageHdr) + mh->data_len); ats_free(mh); - ret = true; + + if (ret < 0) { + return ret; + } } } - return ret; -} /* End ProcessManager::processSignalQueue */ + return 0; +} void ProcessManager::initLMConnection() @@ -197,80 +312,57 @@ ProcessManager::initLMConnection() #else servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family); #endif + if ((local_manager_sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - mgmt_fatal(errno, "[ProcessManager::initLMConnection] Unable to create socket\n"); + Fatal("Unable to create socket '%s': %s", (const char *)sockpath, strerror(errno)); } if (fcntl(local_manager_sockfd, F_SETFD, FD_CLOEXEC) < 0) { - mgmt_fatal(errno, "[ProcessManager::initLMConnection] Unable to set close-on-exec\n"); + Fatal("unable to set close-on-exec flag: %s", strerror(errno)); } if ((connect(local_manager_sockfd, (struct sockaddr *)&serv_addr, servlen)) < 0) { - mgmt_fatal(errno, "[ProcessManager::initLMConnection] failed to connect management socket '%s'\n", (const char *)sockpath); + Fatal("failed to connect management socket '%s': %s", (const char *)sockpath, strerror(errno)); } data_len = sizeof(pid_t); mh_full = (MgmtMessageHdr *)alloca(sizeof(MgmtMessageHdr) + data_len); mh_full->msg_id = MGMT_SIGNAL_PID; mh_full->data_len = data_len; + memcpy((char *)mh_full + sizeof(MgmtMessageHdr), &(pid), data_len); + if (mgmt_write_pipe(local_manager_sockfd, (char *)mh_full, sizeof(MgmtMessageHdr) + data_len) <= 0) { - mgmt_fatal(errno, "[ProcessManager::initLMConnection] Error writing message!\n"); + Fatal("error writing message: %s", strerror(errno)); } +} -} /* End ProcessManager::initLMConnection */ - -void +int ProcessManager::pollLMConnection() { - int res; - - MgmtMessageHdr mh_hdr; - MgmtMessageHdr *mh_full; - char *data_raw; - // Avoid getting stuck enqueuing too many requests in a row, limit to MAX_MSGS_IN_A_ROW. int count; - for (count = 0; count < max_msgs_in_a_row; ++count) { - int num; - num = mgmt_read_timeout(local_manager_sockfd, 1 /* sec */, 0 /* usec */); - if (num == 0) { /* Have nothing */ - break; - } else if (num > 0) { /* We have a message */ - if ((res = mgmt_read_pipe(local_manager_sockfd, (char *)&mh_hdr, sizeof(MgmtMessageHdr))) > 0) { - size_t mh_full_size = sizeof(MgmtMessageHdr) + mh_hdr.data_len; - mh_full = (MgmtMessageHdr *)ats_malloc(mh_full_size); - - memcpy(mh_full, &mh_hdr, sizeof(MgmtMessageHdr)); - data_raw = (char *)mh_full + sizeof(MgmtMessageHdr); - - if ((res = mgmt_read_pipe(local_manager_sockfd, data_raw, mh_hdr.data_len)) > 0) { - Debug("pmgmt", "[ProcessManager::pollLMConnection] Message: '%d'", mh_full->msg_id); - handleMgmtMsgFromLM(mh_full); - } else if (res < 0) { - mgmt_fatal(errno, "[ProcessManager::pollLMConnection] Error in read!"); - } - - ats_free(mh_full); - } else if (res < 0) { - mgmt_fatal(errno, "[ProcessManager::pollLMConnection] Error in read!"); - } + for (count = 0; running && count < max_msgs_in_a_row; ++count) { + MgmtMessageHdr *msg; + int ret = read_management_message(local_manager_sockfd, HRTIME_SECONDS(1), &msg); + if (ret < 0) { + return ret; + } - // handle EOF - if (res == 0) { - close_socket(local_manager_sockfd); - if (!shutdown_event_system) { - mgmt_fatal(0, "[ProcessManager::pollLMConnection] Lost Manager EOF!"); - } - } - } else if (num < 0) { /* Error */ - mgmt_log("[ProcessManager::pollLMConnection] select failed or was interrupted (%d)\n", errno); + // No message, we are done polling. */ + if (msg == nullptr) { + break; } + + Debug("pmgmt", "received message ID %d", msg->msg_id); + handleMgmtMsgFromLM(msg); + ats_free(msg); } - Debug("pmgmt", "[ProcessManager::pollLMConnection] enqueued %d of max %d messages in a row", count, max_msgs_in_a_row); -} /* End ProcessManager::pollLMConnection */ + Debug("pmgmt", "enqueued %d of max %d messages in a row", count, max_msgs_in_a_row); + return 0; +} void ProcessManager::handleMgmtMsgFromLM(MgmtMessageHdr *mh) @@ -322,7 +414,7 @@ ProcessManager::handleMgmtMsgFromLM(MgmtMessageHdr *mh) signalMgmtEntity(MGMT_EVENT_LIFECYCLE_MESSAGE, data_raw, mh->data_len); break; default: - mgmt_log("[ProcessManager::pollLMConnection] unknown type %d\n", mh->msg_id); + Warning("received unknown message ID %d\n", mh->msg_id); break; } } diff --git a/mgmt/ProcessManager.h b/mgmt/ProcessManager.h index 7e728d4e628..c9e27c145f3 100644 --- a/mgmt/ProcessManager.h +++ b/mgmt/ProcessManager.h @@ -45,38 +45,19 @@ class ConfigUpdateCbTable; -void *startProcessManager(void *arg); class ProcessManager : public BaseManager { public: ProcessManager(bool rlm); - ~ProcessManager() - { - close_socket(local_manager_sockfd); - while (!queue_is_empty(mgmt_signal_queue)) { - char *sig = (char *)dequeue(mgmt_signal_queue); - ats_free(sig); - } - ats_free(mgmt_signal_queue); - } - - /** Start a thread for the process manager. + ~ProcessManager(); - If @a cb is set then it is called after the thread is started and before any messages are processed. - */ - void - start(std::function const &cb = std::function()) - { - init = cb; - ink_thread_create(startProcessManager, NULL, 0, 0, NULL); - } + // Start a thread for the process manager. If @a cb is set then it + // is called after the thread is started and before any messages are + // processed. + void start(std::function const &cb = std::function()); - void - stop() - { - mgmt_log("[ProcessManager::stop] Bringing down connection\n"); - close_socket(local_manager_sockfd); - } + // Stop the process manager, dropping any unprocessed messages. + void stop(); inkcoreapi void signalConfigFileChild(const char *parent, const char *child, unsigned int options); inkcoreapi void signalManager(int msg_id, const char *data_str); @@ -84,37 +65,38 @@ class ProcessManager : public BaseManager void reconfigure(); void initLMConnection(); - void pollLMConnection(); void handleMgmtMsgFromLM(MgmtMessageHdr *mh); - bool processEventQueue(); - bool processSignalQueue(); - void registerPluginCallbacks(ConfigUpdateCbTable *_cbtable) { cbtable = _cbtable; } - bool require_lm; - time_t timeout; +private: + int pollLMConnection(); + int processSignalQueue(); + bool processEventQueue(); + bool require_lm; + RecInt timeout; LLQ *mgmt_signal_queue; - pid_t pid; + ink_thread poll_thread = ink_thread_null(); + volatile int running = 0; + /// Thread initialization callback. /// This allows @c traffic_server and @c traffic_manager to perform different initialization in the thread. std::function init; int local_manager_sockfd; - -private: - static const int MAX_MSGS_IN_A_ROW = 10000; - ConfigUpdateCbTable *cbtable; int max_msgs_in_a_row; -}; /* End class ProcessManager */ + + static const int MAX_MSGS_IN_A_ROW = 10000; + static void *processManagerThread(void *arg); +}; inkcoreapi extern ProcessManager *pmgmt; diff --git a/proxy/Main.cc b/proxy/Main.cc index 4242c6e1dcf..96c9f055f08 100644 --- a/proxy/Main.cc +++ b/proxy/Main.cc @@ -91,7 +91,6 @@ extern "C" int plock(int); #include "I_Tasks.h" #include "InkAPIInternal.h" #include "HTTP2.h" -#include "ts/ink_config.h" #include @@ -100,10 +99,6 @@ extern "C" int plock(int); #include #endif -#if TS_USE_GCOV -extern "C" void __gcov_flush(); -#endif - // // Global Data // @@ -169,10 +164,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 +210,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 +238,59 @@ class SignalContinuation : public Continuation 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 +457,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; } @@ -450,23 +478,11 @@ proxy_signal_handler(int signo, siginfo_t *info, void *ctx) ProfilerStop(); #endif -#if TS_USE_GCOV - __gcov_flush(); -#endif - // We don't expect any crashing signals here because, but // forward to the default handler just to be robust. 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 +1303,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 +1683,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 +1939,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