* Foundation. See file COPYING.
*
*/
+#include <poll.h>
+#include <sys/un.h>
#include "common/admin_socket.h"
#include "common/admin_socket_client.h"
+#include "common/dout.h"
#include "common/errno.h"
#include "common/pipe.h"
#include "common/safe_io.h"
+#include "common/Thread.h"
#include "common/version.h"
#include "include/compat.h"
-#include <poll.h>
-#include <sys/un.h>
// re-include our assert to clobber the system one; fix dout:
#include "include/assert.h"
* the application exits normally.
*/
static pthread_mutex_t cleanup_lock = PTHREAD_MUTEX_INITIALIZER;
-static std::vector <const char*> cleanup_files;
+static std::vector<const char*> cleanup_files;
static bool cleanup_atexit = false;
static void remove_cleanup_file(const char *file)
AdminSocket::AdminSocket(CephContext *cct)
- : m_cct(cct),
- m_sock_fd(-1),
- m_shutdown_rd_fd(-1),
- m_shutdown_wr_fd(-1),
- in_hook(false),
- m_lock("AdminSocket::m_lock"),
- m_version_hook(NULL),
- m_help_hook(NULL),
- m_getdescs_hook(NULL)
-{
-}
+ : m_cct(cct)
+{}
AdminSocket::~AdminSocket()
{
return oss.str();
}
- join();
+ th.join();
// Close read end. Doing this before join() blocks the listenter and prevents
// joining.
return "";
}
-void* AdminSocket::entry()
+void AdminSocket::entry() noexcept
{
ldout(m_cct, 5) << "entry start" << dendl;
while (true) {
}
lderr(m_cct) << "AdminSocket: poll(2) error: '"
<< cpp_strerror(err) << dendl;
- return PFL_FAIL;
+ return;
}
if (fds[0].revents & POLLIN) {
}
if (fds[1].revents & POLLIN) {
// Parent wants us to shut down
- return PFL_SUCCESS;
+ return;
}
}
ldout(m_cct, 5) << "entry exit" << dendl;
format = "json-pretty";
cmd_getval(m_cct, cmdmap, "prefix", c);
- m_lock.Lock();
+ std::unique_lock l(lock);
map<string,AdminSocketHook*>::iterator p;
string match = c;
while (match.size()) {
// removing this hook.
in_hook = true;
auto match_hook = p->second;
- m_lock.Unlock();
+ l.unlock();
bool success = (validate(match, cmdmap, out) &&
match_hook->call(match, cmdmap, format, out));
- m_lock.Lock();
+ l.lock();
in_hook = false;
- in_hook_cond.Signal();
+ in_hook_cond.notify_all();
if (!success) {
ldout(m_cct, 0) << "AdminSocket: request '" << match << "' args '" << args
rval = true;
}
}
- m_lock.Unlock();
+ l.unlock();
VOID_TEMP_FAILURE_RETRY(close(connection_fd));
return rval;
std::string_view help)
{
int ret;
- m_lock.Lock();
+ std::unique_lock l(lock);
if (m_hooks.count(command)) {
ldout(m_cct, 5) << "register_command " << command << " hook " << hook << " EEXIST" << dendl;
ret = -EEXIST;
m_help.emplace(command, help);
ret = 0;
}
- m_lock.Unlock();
return ret;
}
int AdminSocket::unregister_command(std::string_view command)
{
int ret;
- m_lock.Lock();
+ std::unique_lock l(lock);
if (m_hooks.count(command)) {
ldout(m_cct, 5) << "unregister_command " << command << dendl;
m_hooks.erase(m_hooks.find(command));
// If we are currently processing a command, wait for it to
// complete in case it referenced the hook that we are
// unregistering.
- if (in_hook) {
- in_hook_cond.Wait(m_lock);
- }
+ in_hook_cond.wait(l, [this]() { return !in_hook; });
ret = 0;
} else {
ldout(m_cct, 5) << "unregister_command " << command << " ENOENT" << dendl;
ret = -ENOENT;
- }
- m_lock.Unlock();
+ }
return ret;
}
register_command("get_command_descriptions", "get_command_descriptions",
m_getdescs_hook, "list available commands");
- create("admin_socket");
+ th = make_named_thread("admin_socket", &AdminSocket::entry, this);
add_cleanup_file(m_path.c_str());
return true;
}
#ifndef CEPH_COMMON_ADMIN_SOCKET_H
#define CEPH_COMMON_ADMIN_SOCKET_H
+#include <condition_variable>
+#include <mutex>
+#include <string>
#include <string_view>
+#include <thread>
-#include "common/Cond.h"
+#include "include/buffer.h"
+#include "common/cmdparse.h"
class AdminSocket;
class CephContext;
+using namespace std::literals;
+
inline constexpr auto CEPH_ADMIN_SOCK_VERSION = "2"sv;
class AdminSocketHook {
virtual ~AdminSocketHook() {}
};
-class AdminSocket : public Thread
+class AdminSocket
{
public:
AdminSocket(CephContext *cct);
- ~AdminSocket() override;
+ ~AdminSocket();
AdminSocket(const AdminSocket&) = delete;
AdminSocket& operator =(const AdminSocket&) = delete;
*/
int unregister_command(std::string_view command);
- bool init(const string& path);
+ bool init(const std::string& path);
void chown(uid_t uid, gid_t gid);
void chmod(mode_t mode);
std::string destroy_shutdown_pipe();
std::string bind_and_listen(const std::string &sock_path, int *fd);
- void *entry() override;
+ std::thread th;
+ void entry() noexcept;
bool do_accept();
bool validate(const std::string& command,
const cmdmap_t& cmdmap,
CephContext *m_cct;
std::string m_path;
- int m_sock_fd;
- int m_shutdown_rd_fd;
- int m_shutdown_wr_fd;
-
- bool in_hook;
- Cond in_hook_cond;
- Mutex m_lock; // protects m_hooks, m_descs, m_help
- AdminSocketHook *m_version_hook, *m_help_hook, *m_getdescs_hook;
+ int m_sock_fd = -1;
+ int m_shutdown_rd_fd = -1;
+ int m_shutdown_wr_fd = -1;
+
+ bool in_hook = false;
+ std::condition_variable in_hook_cond;
+ std::mutex lock; // protects m_hooks, m_descs, m_help
+ AdminSocketHook *m_version_hook = nullptr, *m_help_hook = nullptr,
+ *m_getdescs_hook = nullptr;
std::map<std::string,AdminSocketHook*, std::less<>> m_hooks;
std::map<std::string,std::string, std::less<>> m_descs;