common/admin_socket: close socket descriptor in destructor

Long-running processes that do not reuse a single client connection will
see accumulating file descriptors as a result of not closing the
listening socket.  In this case, eventually the system will reach
file-max and subsequent connections will fail.

Fixes: #11535

Signed-off-by: Jon Bernard <jbernard@tuxion.com>
This commit is contained in:
Jon Bernard 2015-05-08 11:54:06 -04:00
parent 92bcf6c5ec
commit 88fabb1ee6
2 changed files with 40 additions and 11 deletions

View File

@ -149,6 +149,33 @@ std::string AdminSocket::create_shutdown_pipe(int *pipe_rd, int *pipe_wr)
return "";
}
std::string AdminSocket::destroy_shutdown_pipe()
{
// Send a byte to the shutdown pipe that the thread is listening to
char buf[1] = { 0x0 };
int ret = safe_write(m_shutdown_wr_fd, buf, sizeof(buf));
// Close write end
VOID_TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
m_shutdown_wr_fd = -1;
if (ret != 0) {
ostringstream oss;
oss << "AdminSocket::destroy_shutdown_pipe error: failed to write"
"to thread shutdown pipe: error " << ret;
return oss.str();
}
join();
// Close read end. Doing this before join() blocks the listenter and prevents
// joining.
VOID_TEMP_FAILURE_RETRY(close(m_shutdown_rd_fd));
m_shutdown_rd_fd = -1;
return "";
}
std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd)
{
ldout(m_cct, 5) << "bind_and_listen " << sock_path << dendl;
@ -536,30 +563,31 @@ bool AdminSocket::init(const std::string &path)
void AdminSocket::shutdown()
{
std::string err;
// Under normal operation this is unlikely to occur. However for some unit
// tests, some object members are not initialized and so cannot be deleted
// without fault.
if (m_shutdown_wr_fd < 0)
return;
ldout(m_cct, 5) << "shutdown" << dendl;
// Send a byte to the shutdown pipe that the thread is listening to
char buf[1] = { 0x0 };
int ret = safe_write(m_shutdown_wr_fd, buf, sizeof(buf));
VOID_TEMP_FAILURE_RETRY(close(m_shutdown_wr_fd));
m_shutdown_wr_fd = -1;
if (ret == 0) {
join();
} else {
lderr(m_cct) << "AdminSocket::shutdown: failed to write "
"to thread shutdown pipe: error " << ret << dendl;
err = destroy_shutdown_pipe();
if (!err.empty()) {
lderr(m_cct) << "AdminSocket::shutdown: error: " << err << dendl;
}
VOID_TEMP_FAILURE_RETRY(close(m_sock_fd));
unregister_command("version");
unregister_command("git_version");
unregister_command("0");
delete m_version_hook;
unregister_command("help");
delete m_help_hook;
unregister_command("get_command_descriptions");
delete m_getdescs_hook;

View File

@ -79,6 +79,7 @@ private:
void shutdown();
std::string create_shutdown_pipe(int *pipe_rd, int *pipe_wr);
std::string destroy_shutdown_pipe();
std::string bind_and_listen(const std::string &sock_path, int *fd);
void *entry();