nghttpx: Don't stop default loop of worker process on graceful shutdown
To keep ipc channel being read from worker process, default loop should not be stopped. To join all worker threads, now we use dedicated thread to do this. When all worker threads are joined, ev_async_send sends message to default loop, and it is finally stopped.
This commit is contained in:
parent
3fca142e5f
commit
75ff04f87a
|
@ -96,6 +96,12 @@ void ocsp_chld_cb(struct ev_loop *loop, ev_child *w, int revent) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void thread_join_async_cb(struct ev_loop *loop, ev_async *w, int revent) {
|
||||||
|
ev_break(loop);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
ConnectionHandler::ConnectionHandler(struct ev_loop *loop)
|
ConnectionHandler::ConnectionHandler(struct ev_loop *loop)
|
||||||
: single_worker_(nullptr), loop_(loop),
|
: single_worker_(nullptr), loop_(loop),
|
||||||
tls_ticket_key_memcached_get_retry_count_(0),
|
tls_ticket_key_memcached_get_retry_count_(0),
|
||||||
|
@ -110,6 +116,8 @@ ConnectionHandler::ConnectionHandler(struct ev_loop *loop)
|
||||||
ev_io_init(&ocsp_.rev, ocsp_read_cb, -1, EV_READ);
|
ev_io_init(&ocsp_.rev, ocsp_read_cb, -1, EV_READ);
|
||||||
ocsp_.rev.data = this;
|
ocsp_.rev.data = this;
|
||||||
|
|
||||||
|
ev_async_init(&thread_join_asyncev_, thread_join_async_cb);
|
||||||
|
|
||||||
ev_child_init(&ocsp_.chldev, ocsp_chld_cb, 0, 0);
|
ev_child_init(&ocsp_.chldev, ocsp_chld_cb, 0, 0);
|
||||||
ocsp_.chldev.data = this;
|
ocsp_.chldev.data = this;
|
||||||
|
|
||||||
|
@ -120,6 +128,7 @@ ConnectionHandler::ConnectionHandler(struct ev_loop *loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionHandler::~ConnectionHandler() {
|
ConnectionHandler::~ConnectionHandler() {
|
||||||
|
ev_async_stop(loop_, &thread_join_asyncev_);
|
||||||
ev_timer_stop(loop_, &disable_acceptor_timer_);
|
ev_timer_stop(loop_, &disable_acceptor_timer_);
|
||||||
ev_timer_stop(loop_, &ocsp_timer_);
|
ev_timer_stop(loop_, &ocsp_timer_);
|
||||||
|
|
||||||
|
@ -264,9 +273,19 @@ void ConnectionHandler::graceful_shutdown_worker() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &worker : workers_) {
|
for (auto &worker : workers_) {
|
||||||
|
|
||||||
worker->send(wev);
|
worker->send(wev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NOTHREADS
|
||||||
|
ev_async_start(loop_, &thread_join_asyncev_);
|
||||||
|
|
||||||
|
thread_join_fut_ = std::async(std::launch::async, [this]() {
|
||||||
|
(void)reopen_log_files();
|
||||||
|
join_worker();
|
||||||
|
ev_async_send(get_loop(), &thread_join_asyncev_);
|
||||||
|
delete log_config();
|
||||||
|
});
|
||||||
|
#endif // NOTHREADS
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen) {
|
int ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen) {
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#ifndef NOTHREADS
|
||||||
|
#include <future>
|
||||||
|
#endif // NOTHREADS
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
@ -158,6 +161,10 @@ private:
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
ev_timer disable_acceptor_timer_;
|
ev_timer disable_acceptor_timer_;
|
||||||
ev_timer ocsp_timer_;
|
ev_timer ocsp_timer_;
|
||||||
|
ev_async thread_join_asyncev_;
|
||||||
|
#ifndef NOTHREADS
|
||||||
|
std::future<void> thread_join_fut_;
|
||||||
|
#endif // NOTHREADS
|
||||||
size_t tls_ticket_key_memcached_get_retry_count_;
|
size_t tls_ticket_key_memcached_get_retry_count_;
|
||||||
size_t tls_ticket_key_memcached_fail_count_;
|
size_t tls_ticket_key_memcached_fail_count_;
|
||||||
unsigned int worker_round_robin_cnt_;
|
unsigned int worker_round_robin_cnt_;
|
||||||
|
|
|
@ -112,19 +112,14 @@ void graceful_shutdown(ConnectionHandler *conn_handler) {
|
||||||
|
|
||||||
conn_handler->graceful_shutdown_worker();
|
conn_handler->graceful_shutdown_worker();
|
||||||
|
|
||||||
if (get_config()->num_worker == 1 &&
|
if (get_config()->num_worker == 1) {
|
||||||
conn_handler->get_single_worker()->get_worker_stat()->num_connections >
|
if (conn_handler->get_single_worker()->get_worker_stat()->num_connections ==
|
||||||
0) {
|
0) {
|
||||||
return;
|
ev_break(conn_handler->get_loop());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have accepted all pending connections. Shutdown main event
|
return;
|
||||||
// loop.
|
}
|
||||||
|
|
||||||
// TODO this makes IPC from master process impossible. Perhaps, we
|
|
||||||
// should keep alive default loop, and break it once all connections
|
|
||||||
// are terminated somehow.
|
|
||||||
ev_break(conn_handler->get_loop());
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -527,7 +522,6 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
|
|
||||||
ev_run(loop, 0);
|
ev_run(loop, 0);
|
||||||
|
|
||||||
conn_handler.join_worker();
|
|
||||||
conn_handler.cancel_ocsp_update();
|
conn_handler.cancel_ocsp_update();
|
||||||
|
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
|
|
Loading…
Reference in New Issue