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;
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;