]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/admin_socket: close socket descriptor in destructor 4633/head
authorJon Bernard <jbernard@tuxion.com>
Fri, 8 May 2015 15:54:06 +0000 (11:54 -0400)
committerNathan Cutler <ncutler@suse.cz>
Sat, 9 May 2015 20:06:27 +0000 (22:06 +0200)
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>
(cherry picked from commit 88fabb1ee6cd3c7d211ca46919055195e32245db)

src/common/admin_socket.cc
src/common/admin_socket.h

index 4af2904ef3ec4312f6647246cd682603f760fd6a..77048d4d225e7bdaea3e8f78e90486547660880b 100644 (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;
@@ -544,30 +571,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;
 
index 3bc8483434818e851ef142db87eeee983799c74f..5e855bcb5510468862bd3d2ade0d6857df577378 100644 (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();