Merge "snapuserd: Refactor daemon/server." am: 8425f6e6e6 am: de005e145f
Original change: https://android-review.googlesource.com/c/platform/system/core/+/1468410 Change-Id: Ic2bf59f35edfe120faf90caba1cc1816a51ad4c1
This commit is contained in:
commit
975d3eb45f
7 changed files with 193 additions and 186 deletions
|
|
@ -403,7 +403,7 @@ cc_defaults {
|
||||||
],
|
],
|
||||||
srcs: [
|
srcs: [
|
||||||
"snapuserd_server.cpp",
|
"snapuserd_server.cpp",
|
||||||
"snapuserd.cpp",
|
"snapuserd.cpp",
|
||||||
"snapuserd_daemon.cpp",
|
"snapuserd_daemon.cpp",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
@ -558,7 +558,7 @@ cc_test {
|
||||||
"libbrotli",
|
"libbrotli",
|
||||||
"libgtest",
|
"libgtest",
|
||||||
"libsnapshot_cow",
|
"libsnapshot_cow",
|
||||||
"libsnapshot_snapuserd",
|
"libsnapshot_snapuserd",
|
||||||
"libcutils_sockets",
|
"libcutils_sockets",
|
||||||
"libz",
|
"libz",
|
||||||
"libdm",
|
"libdm",
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ namespace snapshot {
|
||||||
static constexpr uint32_t PACKET_SIZE = 512;
|
static constexpr uint32_t PACKET_SIZE = 512;
|
||||||
static constexpr uint32_t MAX_CONNECT_RETRY_COUNT = 10;
|
static constexpr uint32_t MAX_CONNECT_RETRY_COUNT = 10;
|
||||||
|
|
||||||
|
static constexpr char kSnapuserdSocketFirstStage[] = "snapuserd_first_stage";
|
||||||
|
static constexpr char kSnapuserdSocket[] = "snapuserd";
|
||||||
|
|
||||||
class SnapuserdClient {
|
class SnapuserdClient {
|
||||||
private:
|
private:
|
||||||
int sockfd_ = 0;
|
int sockfd_ = 0;
|
||||||
|
|
|
||||||
|
|
@ -25,22 +25,21 @@ class Daemon {
|
||||||
// The Daemon class is a singleton to avoid
|
// The Daemon class is a singleton to avoid
|
||||||
// instantiating more than once
|
// instantiating more than once
|
||||||
public:
|
public:
|
||||||
|
Daemon() {}
|
||||||
|
|
||||||
static Daemon& Instance() {
|
static Daemon& Instance() {
|
||||||
static Daemon instance;
|
static Daemon instance;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
int StartServer(std::string socketname);
|
bool StartServer(const std::string& socketname);
|
||||||
bool IsRunning();
|
|
||||||
void Run();
|
void Run();
|
||||||
|
void Interrupt();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_running_;
|
|
||||||
std::unique_ptr<struct pollfd> poll_fd_;
|
|
||||||
// Signal mask used with ppoll()
|
// Signal mask used with ppoll()
|
||||||
sigset_t signal_mask_;
|
sigset_t signal_mask_;
|
||||||
|
|
||||||
Daemon();
|
|
||||||
Daemon(Daemon const&) = delete;
|
Daemon(Daemon const&) = delete;
|
||||||
void operator=(Daemon const&) = delete;
|
void operator=(Daemon const&) = delete;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -34,12 +36,11 @@ static constexpr uint32_t MAX_PACKET_SIZE = 512;
|
||||||
enum class DaemonOperations {
|
enum class DaemonOperations {
|
||||||
START,
|
START,
|
||||||
QUERY,
|
QUERY,
|
||||||
TERMINATING,
|
|
||||||
STOP,
|
STOP,
|
||||||
INVALID,
|
INVALID,
|
||||||
};
|
};
|
||||||
|
|
||||||
class Client {
|
class DmUserHandler {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<std::thread> threadHandler_;
|
std::unique_ptr<std::thread> threadHandler_;
|
||||||
|
|
||||||
|
|
@ -77,7 +78,15 @@ class SnapuserdServer : public Stoppable {
|
||||||
private:
|
private:
|
||||||
android::base::unique_fd sockfd_;
|
android::base::unique_fd sockfd_;
|
||||||
bool terminating_;
|
bool terminating_;
|
||||||
std::vector<std::unique_ptr<Client>> clients_vec_;
|
std::vector<std::unique_ptr<DmUserHandler>> dm_users_;
|
||||||
|
std::vector<struct pollfd> watched_fds_;
|
||||||
|
|
||||||
|
void AddWatchedFd(android::base::borrowed_fd fd);
|
||||||
|
void AcceptClient();
|
||||||
|
bool HandleClient(android::base::borrowed_fd fd, int revents);
|
||||||
|
bool Recv(android::base::borrowed_fd fd, std::string* data);
|
||||||
|
bool Sendmsg(android::base::borrowed_fd fd, const std::string& msg);
|
||||||
|
bool Receivemsg(android::base::borrowed_fd fd, const std::string& msg);
|
||||||
|
|
||||||
void ThreadStart(std::string cow_device, std::string backing_device,
|
void ThreadStart(std::string cow_device, std::string backing_device,
|
||||||
std::string control_device) override;
|
std::string control_device) override;
|
||||||
|
|
@ -92,13 +101,11 @@ class SnapuserdServer : public Stoppable {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SnapuserdServer() { terminating_ = false; }
|
SnapuserdServer() { terminating_ = false; }
|
||||||
|
~SnapuserdServer();
|
||||||
|
|
||||||
int Start(std::string socketname);
|
bool Start(const std::string& socketname);
|
||||||
int AcceptClient();
|
bool Run();
|
||||||
int Receivemsg(int fd);
|
void Interrupt();
|
||||||
int Sendmsg(int fd, char* msg, size_t len);
|
|
||||||
std::string Recvmsg(int fd, int* ret);
|
|
||||||
android::base::borrowed_fd GetSocketFd() { return sockfd_; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace snapshot
|
} // namespace snapshot
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
|
||||||
#include <libsnapshot/snapuserd.h>
|
#include <libsnapshot/snapuserd.h>
|
||||||
|
#include <libsnapshot/snapuserd_client.h>
|
||||||
#include <libsnapshot/snapuserd_daemon.h>
|
#include <libsnapshot/snapuserd_daemon.h>
|
||||||
#include <libsnapshot/snapuserd_server.h>
|
#include <libsnapshot/snapuserd_server.h>
|
||||||
|
|
||||||
|
|
@ -482,13 +483,13 @@ int Snapuserd::WriteDmUserPayload(size_t size) {
|
||||||
bool Snapuserd::Init() {
|
bool Snapuserd::Init() {
|
||||||
backing_store_fd_.reset(open(backing_store_device_.c_str(), O_RDONLY));
|
backing_store_fd_.reset(open(backing_store_device_.c_str(), O_RDONLY));
|
||||||
if (backing_store_fd_ < 0) {
|
if (backing_store_fd_ < 0) {
|
||||||
LOG(ERROR) << "Open Failed: " << backing_store_device_;
|
PLOG(ERROR) << "Open Failed: " << backing_store_device_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cow_fd_.reset(open(cow_device_.c_str(), O_RDWR));
|
cow_fd_.reset(open(cow_device_.c_str(), O_RDWR));
|
||||||
if (cow_fd_ < 0) {
|
if (cow_fd_ < 0) {
|
||||||
LOG(ERROR) << "Open Failed: " << cow_device_;
|
PLOG(ERROR) << "Open Failed: " << cow_device_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,7 +499,7 @@ bool Snapuserd::Init() {
|
||||||
|
|
||||||
ctrl_fd_.reset(open(control_path.c_str(), O_RDWR));
|
ctrl_fd_.reset(open(control_path.c_str(), O_RDWR));
|
||||||
if (ctrl_fd_ < 0) {
|
if (ctrl_fd_ < 0) {
|
||||||
LOG(ERROR) << "Unable to open " << control_path;
|
PLOG(ERROR) << "Unable to open " << control_path;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -629,7 +630,11 @@ int main([[maybe_unused]] int argc, char** argv) {
|
||||||
|
|
||||||
android::snapshot::Daemon& daemon = android::snapshot::Daemon::Instance();
|
android::snapshot::Daemon& daemon = android::snapshot::Daemon::Instance();
|
||||||
|
|
||||||
daemon.StartServer(argv[1]);
|
std::string socket = android::snapshot::kSnapuserdSocket;
|
||||||
|
if (argc >= 2) {
|
||||||
|
socket = argv[1];
|
||||||
|
}
|
||||||
|
daemon.StartServer(socket);
|
||||||
daemon.Run();
|
daemon.Run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -20,16 +20,12 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace snapshot {
|
namespace snapshot {
|
||||||
|
|
||||||
int Daemon::StartServer(std::string socketname) {
|
bool Daemon::StartServer(const std::string& socketname) {
|
||||||
int ret;
|
if (!server_.Start(socketname)) {
|
||||||
|
|
||||||
ret = server_.Start(socketname);
|
|
||||||
if (ret < 0) {
|
|
||||||
LOG(ERROR) << "Snapuserd daemon failed to start...";
|
LOG(ERROR) << "Snapuserd daemon failed to start...";
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Daemon::MaskAllSignalsExceptIntAndTerm() {
|
void Daemon::MaskAllSignalsExceptIntAndTerm() {
|
||||||
|
|
@ -51,51 +47,26 @@ void Daemon::MaskAllSignals() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Daemon::Daemon() {
|
|
||||||
is_running_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Daemon::IsRunning() {
|
|
||||||
return is_running_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Daemon::Run() {
|
void Daemon::Run() {
|
||||||
poll_fd_ = std::make_unique<struct pollfd>();
|
|
||||||
poll_fd_->fd = server_.GetSocketFd().get();
|
|
||||||
poll_fd_->events = POLLIN;
|
|
||||||
|
|
||||||
sigfillset(&signal_mask_);
|
sigfillset(&signal_mask_);
|
||||||
sigdelset(&signal_mask_, SIGINT);
|
sigdelset(&signal_mask_, SIGINT);
|
||||||
sigdelset(&signal_mask_, SIGTERM);
|
sigdelset(&signal_mask_, SIGTERM);
|
||||||
|
|
||||||
// Masking signals here ensure that after this point, we won't handle INT/TERM
|
// Masking signals here ensure that after this point, we won't handle INT/TERM
|
||||||
// until after we call into ppoll()
|
// until after we call into ppoll()
|
||||||
MaskAllSignals();
|
|
||||||
signal(SIGINT, Daemon::SignalHandler);
|
signal(SIGINT, Daemon::SignalHandler);
|
||||||
signal(SIGTERM, Daemon::SignalHandler);
|
signal(SIGTERM, Daemon::SignalHandler);
|
||||||
signal(SIGPIPE, Daemon::SignalHandler);
|
signal(SIGPIPE, Daemon::SignalHandler);
|
||||||
|
|
||||||
LOG(DEBUG) << "Snapuserd-server: ready to accept connections";
|
LOG(DEBUG) << "Snapuserd-server: ready to accept connections";
|
||||||
|
|
||||||
while (IsRunning()) {
|
MaskAllSignalsExceptIntAndTerm();
|
||||||
int ret = ppoll(poll_fd_.get(), 1, nullptr, &signal_mask_);
|
|
||||||
MaskAllSignalsExceptIntAndTerm();
|
|
||||||
|
|
||||||
if (ret == -1) {
|
server_.Run();
|
||||||
PLOG(ERROR) << "Snapuserd:ppoll error";
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (poll_fd_->revents == POLLIN) {
|
void Daemon::Interrupt() {
|
||||||
if (server_.AcceptClient() == static_cast<int>(DaemonOperations::STOP)) {
|
server_.Interrupt();
|
||||||
Daemon::Instance().is_running_ = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mask all signals to ensure that is_running_ can't become false between
|
|
||||||
// checking it in the while condition and calling into ppoll()
|
|
||||||
MaskAllSignals();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Daemon::SignalHandler(int signal) {
|
void Daemon::SignalHandler(int signal) {
|
||||||
|
|
@ -103,7 +74,7 @@ void Daemon::SignalHandler(int signal) {
|
||||||
switch (signal) {
|
switch (signal) {
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
case SIGTERM: {
|
case SIGTERM: {
|
||||||
Daemon::Instance().is_running_ = false;
|
Daemon::Instance().Interrupt();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIGPIPE: {
|
case SIGPIPE: {
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,18 @@ namespace snapshot {
|
||||||
DaemonOperations SnapuserdServer::Resolveop(std::string& input) {
|
DaemonOperations SnapuserdServer::Resolveop(std::string& input) {
|
||||||
if (input == "start") return DaemonOperations::START;
|
if (input == "start") return DaemonOperations::START;
|
||||||
if (input == "stop") return DaemonOperations::STOP;
|
if (input == "stop") return DaemonOperations::STOP;
|
||||||
if (input == "terminate-request") return DaemonOperations::TERMINATING;
|
|
||||||
if (input == "query") return DaemonOperations::QUERY;
|
if (input == "query") return DaemonOperations::QUERY;
|
||||||
|
|
||||||
return DaemonOperations::INVALID;
|
return DaemonOperations::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SnapuserdServer::~SnapuserdServer() {
|
||||||
|
// Close any client sockets that were added via AcceptClient().
|
||||||
|
for (size_t i = 1; i < watched_fds_.size(); i++) {
|
||||||
|
close(watched_fds_[i].fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string SnapuserdServer::GetDaemonStatus() {
|
std::string SnapuserdServer::GetDaemonStatus() {
|
||||||
std::string msg = "";
|
std::string msg = "";
|
||||||
|
|
||||||
|
|
@ -67,7 +73,7 @@ void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_de
|
||||||
std::string control_device) {
|
std::string control_device) {
|
||||||
Snapuserd snapd(cow_device, backing_device, control_device);
|
Snapuserd snapd(cow_device, backing_device, control_device);
|
||||||
if (!snapd.Init()) {
|
if (!snapd.Init()) {
|
||||||
PLOG(ERROR) << "Snapuserd: Init failed";
|
LOG(ERROR) << "Snapuserd: Init failed";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,158 +90,174 @@ void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_de
|
||||||
void SnapuserdServer::ShutdownThreads() {
|
void SnapuserdServer::ShutdownThreads() {
|
||||||
StopThreads();
|
StopThreads();
|
||||||
|
|
||||||
for (auto& client : clients_vec_) {
|
for (auto& client : dm_users_) {
|
||||||
auto& th = client->GetThreadHandler();
|
auto& th = client->GetThreadHandler();
|
||||||
|
|
||||||
if (th->joinable()) th->join();
|
if (th->joinable()) th->join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int SnapuserdServer::Sendmsg(int fd, char* msg, size_t size) {
|
bool SnapuserdServer::Sendmsg(android::base::borrowed_fd fd, const std::string& msg) {
|
||||||
int ret = TEMP_FAILURE_RETRY(send(fd, (char*)msg, size, 0));
|
ssize_t ret = TEMP_FAILURE_RETRY(send(fd.get(), msg.data(), msg.size(), 0));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
PLOG(ERROR) << "Snapuserd:server: send() failed";
|
PLOG(ERROR) << "Snapuserd:server: send() failed";
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < size) {
|
if (ret < msg.size()) {
|
||||||
PLOG(ERROR) << "Partial data sent";
|
LOG(ERROR) << "Partial send; expected " << msg.size() << " bytes, sent " << ret;
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SnapuserdServer::Recvmsg(int fd, int* ret) {
|
bool SnapuserdServer::Recv(android::base::borrowed_fd fd, std::string* data) {
|
||||||
struct timeval tv;
|
|
||||||
fd_set set;
|
|
||||||
char msg[MAX_PACKET_SIZE];
|
char msg[MAX_PACKET_SIZE];
|
||||||
|
ssize_t rv = TEMP_FAILURE_RETRY(recv(fd.get(), msg, sizeof(msg), 0));
|
||||||
|
if (rv < 0) {
|
||||||
|
PLOG(ERROR) << "recv failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*data = std::string(msg, rv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
tv.tv_sec = 2;
|
bool SnapuserdServer::Receivemsg(android::base::borrowed_fd fd, const std::string& str) {
|
||||||
tv.tv_usec = 0;
|
const char delim = ',';
|
||||||
FD_ZERO(&set);
|
|
||||||
FD_SET(fd, &set);
|
std::vector<std::string> out;
|
||||||
*ret = select(fd + 1, &set, NULL, NULL, &tv);
|
Parsemsg(str, delim, out);
|
||||||
if (*ret == -1) { // select failed
|
DaemonOperations op = Resolveop(out[0]);
|
||||||
return {};
|
|
||||||
} else if (*ret == 0) { // timeout
|
switch (op) {
|
||||||
return {};
|
case DaemonOperations::START: {
|
||||||
|
// Message format:
|
||||||
|
// start,<cow_device_path>,<source_device_path>,<control_device>
|
||||||
|
//
|
||||||
|
// Start the new thread which binds to dm-user misc device
|
||||||
|
auto handler = std::make_unique<DmUserHandler>();
|
||||||
|
handler->SetThreadHandler(
|
||||||
|
std::bind(&SnapuserdServer::ThreadStart, this, out[1], out[2], out[3]));
|
||||||
|
dm_users_.push_back(std::move(handler));
|
||||||
|
return Sendmsg(fd, "success");
|
||||||
|
}
|
||||||
|
case DaemonOperations::STOP: {
|
||||||
|
// Message format: stop
|
||||||
|
//
|
||||||
|
// Stop all the threads gracefully and then shutdown the
|
||||||
|
// main thread
|
||||||
|
SetTerminating();
|
||||||
|
ShutdownThreads();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case DaemonOperations::QUERY: {
|
||||||
|
// Message format: query
|
||||||
|
//
|
||||||
|
// As part of transition, Second stage daemon will be
|
||||||
|
// created before terminating the first stage daemon. Hence,
|
||||||
|
// for a brief period client may have to distiguish between
|
||||||
|
// first stage daemon and second stage daemon.
|
||||||
|
//
|
||||||
|
// Second stage daemon is marked as active and hence will
|
||||||
|
// be ready to receive control message.
|
||||||
|
return Sendmsg(fd, GetDaemonStatus());
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
LOG(ERROR) << "Received unknown message type from client";
|
||||||
|
Sendmsg(fd, "fail");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SnapuserdServer::Start(const std::string& socketname) {
|
||||||
|
sockfd_.reset(android_get_control_socket(socketname.c_str()));
|
||||||
|
if (sockfd_ >= 0) {
|
||||||
|
if (listen(sockfd_.get(), 4) < 0) {
|
||||||
|
PLOG(ERROR) << "listen socket failed: " << socketname;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*ret = TEMP_FAILURE_RETRY(recv(fd, msg, MAX_PACKET_SIZE, 0));
|
sockfd_.reset(socket_local_server(socketname.c_str(), ANDROID_SOCKET_NAMESPACE_RESERVED,
|
||||||
if (*ret < 0) {
|
SOCK_STREAM));
|
||||||
PLOG(ERROR) << "Snapuserd:server: recv failed";
|
if (sockfd_ < 0) {
|
||||||
return {};
|
PLOG(ERROR) << "Failed to create server socket " << socketname;
|
||||||
} else if (*ret == 0) {
|
return false;
|
||||||
LOG(DEBUG) << "Snapuserd client disconnected";
|
|
||||||
return {};
|
|
||||||
} else {
|
|
||||||
std::string str(msg);
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int SnapuserdServer::Receivemsg(int fd) {
|
AddWatchedFd(sockfd_);
|
||||||
char msg[MAX_PACKET_SIZE];
|
|
||||||
std::unique_ptr<Client> newClient;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
memset(msg, '\0', MAX_PACKET_SIZE);
|
|
||||||
std::string str = Recvmsg(fd, &ret);
|
|
||||||
|
|
||||||
if (ret <= 0) {
|
|
||||||
LOG(DEBUG) << "recv failed with ret: " << ret;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char delim = ',';
|
|
||||||
|
|
||||||
std::vector<std::string> out;
|
|
||||||
Parsemsg(str, delim, out);
|
|
||||||
DaemonOperations op = Resolveop(out[0]);
|
|
||||||
memset(msg, '\0', MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
switch (op) {
|
|
||||||
case DaemonOperations::START: {
|
|
||||||
// Message format:
|
|
||||||
// start,<cow_device_path>,<source_device_path>,<control_device>
|
|
||||||
//
|
|
||||||
// Start the new thread which binds to dm-user misc device
|
|
||||||
newClient = std::make_unique<Client>();
|
|
||||||
newClient->SetThreadHandler(
|
|
||||||
std::bind(&SnapuserdServer::ThreadStart, this, out[1], out[2], out[3]));
|
|
||||||
clients_vec_.push_back(std::move(newClient));
|
|
||||||
sprintf(msg, "success");
|
|
||||||
Sendmsg(fd, msg, MAX_PACKET_SIZE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case DaemonOperations::STOP: {
|
|
||||||
// Message format: stop
|
|
||||||
//
|
|
||||||
// Stop all the threads gracefully and then shutdown the
|
|
||||||
// main thread
|
|
||||||
ShutdownThreads();
|
|
||||||
return static_cast<int>(DaemonOperations::STOP);
|
|
||||||
}
|
|
||||||
case DaemonOperations::TERMINATING: {
|
|
||||||
// Message format: terminate-request
|
|
||||||
//
|
|
||||||
// This is invoked during transition. First stage
|
|
||||||
// daemon will receive this request. First stage daemon
|
|
||||||
// will be considered as a passive daemon from hereon.
|
|
||||||
SetTerminating();
|
|
||||||
sprintf(msg, "success");
|
|
||||||
Sendmsg(fd, msg, MAX_PACKET_SIZE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case DaemonOperations::QUERY: {
|
|
||||||
// Message format: query
|
|
||||||
//
|
|
||||||
// As part of transition, Second stage daemon will be
|
|
||||||
// created before terminating the first stage daemon. Hence,
|
|
||||||
// for a brief period client may have to distiguish between
|
|
||||||
// first stage daemon and second stage daemon.
|
|
||||||
//
|
|
||||||
// Second stage daemon is marked as active and hence will
|
|
||||||
// be ready to receive control message.
|
|
||||||
std::string dstr = GetDaemonStatus();
|
|
||||||
memcpy(msg, dstr.c_str(), dstr.size());
|
|
||||||
Sendmsg(fd, msg, MAX_PACKET_SIZE);
|
|
||||||
if (dstr == "active")
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
sprintf(msg, "fail");
|
|
||||||
Sendmsg(fd, msg, MAX_PACKET_SIZE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int SnapuserdServer::Start(std::string socketname) {
|
|
||||||
sockfd_.reset(socket_local_server(socketname.c_str(), ANDROID_SOCKET_NAMESPACE_RESERVED,
|
|
||||||
SOCK_STREAM));
|
|
||||||
if (sockfd_ < 0) {
|
|
||||||
PLOG(ERROR) << "Failed to create server socket " << socketname;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(DEBUG) << "Snapuserd server successfully started with socket name " << socketname;
|
LOG(DEBUG) << "Snapuserd server successfully started with socket name " << socketname;
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SnapuserdServer::AcceptClient() {
|
bool SnapuserdServer::Run() {
|
||||||
int fd = accept(sockfd_.get(), NULL, NULL);
|
while (!IsTerminating()) {
|
||||||
|
int rv = TEMP_FAILURE_RETRY(poll(watched_fds_.data(), watched_fds_.size(), -1));
|
||||||
|
if (rv < 0) {
|
||||||
|
PLOG(ERROR) << "poll failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!rv) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watched_fds_[0].revents) {
|
||||||
|
AcceptClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = watched_fds_.begin() + 1;
|
||||||
|
while (iter != watched_fds_.end()) {
|
||||||
|
if (iter->revents && !HandleClient(iter->fd, iter->revents)) {
|
||||||
|
close(iter->fd);
|
||||||
|
iter = watched_fds_.erase(iter);
|
||||||
|
} else {
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnapuserdServer::AddWatchedFd(android::base::borrowed_fd fd) {
|
||||||
|
struct pollfd p = {};
|
||||||
|
p.fd = fd.get();
|
||||||
|
p.events = POLLIN;
|
||||||
|
watched_fds_.emplace_back(std::move(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnapuserdServer::AcceptClient() {
|
||||||
|
int fd = TEMP_FAILURE_RETRY(accept4(sockfd_.get(), nullptr, nullptr, SOCK_CLOEXEC));
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
PLOG(ERROR) << "Socket accept failed: " << strerror(errno);
|
PLOG(ERROR) << "accept4 failed";
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Receivemsg(fd);
|
AddWatchedFd(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SnapuserdServer::HandleClient(android::base::borrowed_fd fd, int revents) {
|
||||||
|
if (revents & POLLHUP) {
|
||||||
|
LOG(DEBUG) << "Snapuserd client disconnected";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string str;
|
||||||
|
if (!Recv(fd, &str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Receivemsg(fd, str)) {
|
||||||
|
LOG(ERROR) << "Encountered error handling client message, revents: " << revents;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SnapuserdServer::Interrupt() {
|
||||||
|
// Force close the socket so poll() fails.
|
||||||
|
sockfd_ = {};
|
||||||
|
SetTerminating();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace snapshot
|
} // namespace snapshot
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue