Merge "libsnapshot:snapuserd: Handle signals"

This commit is contained in:
Akilesh Kailash 2020-10-08 02:49:04 +00:00 committed by Gerrit Code Review
commit c81477c5e4
8 changed files with 185 additions and 43 deletions

View file

@ -65,7 +65,7 @@ class Snapuserd final {
backing_store_device_(in_backing_store_device), backing_store_device_(in_backing_store_device),
metadata_read_done_(false) {} metadata_read_done_(false) {}
int Init(); bool Init();
int Run(); int Run();
int ReadDmUserHeader(); int ReadDmUserHeader();
int WriteDmUserPayload(size_t size); int WriteDmUserPayload(size_t size);

View file

@ -14,22 +14,8 @@
#pragma once #pragma once
#include <arpa/inet.h>
#include <cutils/sockets.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <chrono>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <sstream>
#include <string> #include <string>
#include <thread> #include <thread>
#include <vector> #include <vector>

View file

@ -14,6 +14,8 @@
#pragma once #pragma once
#include <poll.h>
#include <libsnapshot/snapuserd_server.h> #include <libsnapshot/snapuserd_server.h>
namespace android { namespace android {
@ -34,12 +36,17 @@ class Daemon {
private: private:
bool is_running_; bool is_running_;
std::unique_ptr<struct pollfd> poll_fd_;
// Signal mask used with ppoll()
sigset_t signal_mask_;
Daemon(); Daemon();
Daemon(Daemon const&) = delete; Daemon(Daemon const&) = delete;
void operator=(Daemon const&) = delete; void operator=(Daemon const&) = delete;
SnapuserdServer server_; SnapuserdServer server_;
void MaskAllSignalsExceptIntAndTerm();
void MaskAllSignals();
static void SignalHandler(int signal); static void SignalHandler(int signal);
}; };

View file

@ -14,18 +14,6 @@
#pragma once #pragma once
#include <stdint.h>
#include <arpa/inet.h>
#include <cutils/sockets.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <functional> #include <functional>
@ -89,6 +77,7 @@ class SnapuserdServer : public Stoppable {
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<Client>> clients_vec_;
void ThreadStart(std::string cow_device, std::string backing_device) override; void ThreadStart(std::string cow_device, std::string backing_device) override;
void ShutdownThreads(); void ShutdownThreads();
DaemonOperations Resolveop(std::string& input); DaemonOperations Resolveop(std::string& input);
@ -100,8 +89,6 @@ class SnapuserdServer : public Stoppable {
bool IsTerminating() { return terminating_; } bool IsTerminating() { return terminating_; }
public: public:
~SnapuserdServer() { clients_vec_.clear(); }
SnapuserdServer() { terminating_ = false; } SnapuserdServer() { terminating_ = false; }
int Start(std::string socketname); int Start(std::string socketname);
@ -109,6 +96,7 @@ class SnapuserdServer : public Stoppable {
int Receivemsg(int fd); int Receivemsg(int fd);
int Sendmsg(int fd, char* msg, size_t len); int Sendmsg(int fd, char* msg, size_t len);
std::string Recvmsg(int fd, int* ret); std::string Recvmsg(int fd, int* ret);
android::base::borrowed_fd GetSocketFd() { return sockfd_; }
}; };
} // namespace snapshot } // namespace snapshot

View file

@ -485,17 +485,17 @@ int Snapuserd::WriteDmUserPayload(size_t size) {
return sizeof(struct dm_user_header) + size; return sizeof(struct dm_user_header) + size;
} }
int 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_; LOG(ERROR) << "Open Failed: " << backing_store_device_;
return 1; 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_; LOG(ERROR) << "Open Failed: " << cow_device_;
return 1; return false;
} }
std::string str(cow_device_); std::string str(cow_device_);
@ -509,7 +509,7 @@ int Snapuserd::Init() {
std::string uuid; std::string uuid;
if (!dm.GetDmDeviceUuidByName(device_name, &uuid)) { if (!dm.GetDmDeviceUuidByName(device_name, &uuid)) {
LOG(ERROR) << "Unable to find UUID for " << cow_device_; LOG(ERROR) << "Unable to find UUID for " << cow_device_;
return 1; return false;
} }
LOG(DEBUG) << "UUID: " << uuid; LOG(DEBUG) << "UUID: " << uuid;
@ -518,7 +518,7 @@ int Snapuserd::Init() {
ctrl_fd_.reset(open(t.control_path().c_str(), O_RDWR)); ctrl_fd_.reset(open(t.control_path().c_str(), O_RDWR));
if (ctrl_fd_ < 0) { if (ctrl_fd_ < 0) {
LOG(ERROR) << "Unable to open " << t.control_path(); LOG(ERROR) << "Unable to open " << t.control_path();
return 1; return false;
} }
// Allocate the buffer which is used to communicate between // Allocate the buffer which is used to communicate between
@ -528,7 +528,7 @@ int Snapuserd::Init() {
size_t buf_size = sizeof(struct dm_user_header) + PAYLOAD_SIZE; size_t buf_size = sizeof(struct dm_user_header) + PAYLOAD_SIZE;
bufsink_.Initialize(buf_size); bufsink_.Initialize(buf_size);
return 0; return true;
} }
int Snapuserd::Run() { int Snapuserd::Run() {
@ -601,6 +601,11 @@ int Snapuserd::Run() {
ret = ReadData(chunk + num_chunks_read, read_size); ret = ReadData(chunk + num_chunks_read, read_size);
if (ret < 0) { if (ret < 0) {
LOG(ERROR) << "ReadData failed"; LOG(ERROR) << "ReadData failed";
// TODO: Bug 168259959: All the error paths from this function
// should send error code to dm-user thereby IO
// terminates with an error from dm-user. Returning
// here without sending error code will block the
// IO.
return ret; return ret;
} }
} }
@ -622,7 +627,7 @@ int Snapuserd::Run() {
} }
case DM_USER_MAP_WRITE: { case DM_USER_MAP_WRITE: {
// TODO: After merge operation is completed, kernel issues write // TODO: Bug: 168311203: After merge operation is completed, kernel issues write
// to flush all the exception mappings where the merge is // to flush all the exception mappings where the merge is
// completed. If dm-user routes the WRITE IO, we need to clear // completed. If dm-user routes the WRITE IO, we need to clear
// in-memory data structures representing those exception // in-memory data structures representing those exception

View file

@ -1,3 +1,33 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <arpa/inet.h>
#include <cutils/sockets.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <chrono>
#include <android-base/logging.h> #include <android-base/logging.h>
#include <libsnapshot/snapuserd_client.h> #include <libsnapshot/snapuserd_client.h>
@ -67,6 +97,37 @@ int SnapuserdClient::Sendmsg(const char* msg, size_t size) {
return 0; return 0;
} }
std::string SnapuserdClient::Receivemsg() {
int ret;
struct timeval tv;
fd_set set;
char msg[PACKET_SIZE];
std::string msgStr("fail");
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&set);
FD_SET(sockfd_, &set);
ret = select(sockfd_ + 1, &set, NULL, NULL, &tv);
if (ret == -1) { // select failed
LOG(ERROR) << "Snapuserd:client: Select call failed";
} else if (ret == 0) { // timeout
LOG(ERROR) << "Snapuserd:client: Select call timeout";
} else {
ret = TEMP_FAILURE_RETRY(recv(sockfd_, msg, PACKET_SIZE, 0));
if (ret < 0) {
PLOG(ERROR) << "Snapuserd:client: recv failed";
} else if (ret == 0) {
LOG(DEBUG) << "Snapuserd:client disconnected";
} else {
msgStr.clear();
msgStr = msg;
}
}
return msgStr;
}
#if 0
std::string SnapuserdClient::Receivemsg() { std::string SnapuserdClient::Receivemsg() {
char msg[PACKET_SIZE]; char msg[PACKET_SIZE];
std::string msgStr("fail"); std::string msgStr("fail");
@ -82,6 +143,7 @@ std::string SnapuserdClient::Receivemsg() {
msgStr = msg; msgStr = msg;
return msgStr; return msgStr;
} }
#endif
int SnapuserdClient::StopSnapuserd(bool firstStageDaemon) { int SnapuserdClient::StopSnapuserd(bool firstStageDaemon) {
if (firstStageDaemon) { if (firstStageDaemon) {

View file

@ -1,3 +1,19 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <android-base/logging.h> #include <android-base/logging.h>
#include <libsnapshot/snapuserd_daemon.h> #include <libsnapshot/snapuserd_daemon.h>
@ -16,11 +32,27 @@ int Daemon::StartServer(std::string socketname) {
return ret; return ret;
} }
void Daemon::MaskAllSignalsExceptIntAndTerm() {
sigset_t signal_mask;
sigfillset(&signal_mask);
sigdelset(&signal_mask, SIGINT);
sigdelset(&signal_mask, SIGTERM);
sigdelset(&signal_mask, SIGPIPE);
if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
PLOG(ERROR) << "Failed to set sigprocmask";
}
}
void Daemon::MaskAllSignals() {
sigset_t signal_mask;
sigfillset(&signal_mask);
if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
PLOG(ERROR) << "Couldn't mask all signals";
}
}
Daemon::Daemon() { Daemon::Daemon() {
is_running_ = true; is_running_ = true;
// TODO: Mask other signals - Bug 168258493
signal(SIGINT, Daemon::SignalHandler);
signal(SIGTERM, Daemon::SignalHandler);
} }
bool Daemon::IsRunning() { bool Daemon::IsRunning() {
@ -28,10 +60,41 @@ bool Daemon::IsRunning() {
} }
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_);
sigdelset(&signal_mask_, SIGINT);
sigdelset(&signal_mask_, SIGTERM);
// Masking signals here ensure that after this point, we won't handle INT/TERM
// until after we call into ppoll()
MaskAllSignals();
signal(SIGINT, Daemon::SignalHandler);
signal(SIGTERM, Daemon::SignalHandler);
signal(SIGPIPE, Daemon::SignalHandler);
LOG(DEBUG) << "Snapuserd-server: ready to accept connections";
while (IsRunning()) { while (IsRunning()) {
if (server_.AcceptClient() == static_cast<int>(DaemonOperations::STOP)) { int ret = ppoll(poll_fd_.get(), 1, nullptr, &signal_mask_);
Daemon::Instance().is_running_ = false; MaskAllSignalsExceptIntAndTerm();
if (ret == -1) {
PLOG(ERROR) << "Snapuserd:ppoll error";
break;
} }
if (poll_fd_->revents == POLLIN) {
if (server_.AcceptClient() == static_cast<int>(DaemonOperations::STOP)) {
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();
} }
} }
@ -43,6 +106,10 @@ void Daemon::SignalHandler(int signal) {
Daemon::Instance().is_running_ = false; Daemon::Instance().is_running_ = false;
break; break;
} }
case SIGPIPE: {
LOG(ERROR) << "Received SIGPIPE signal";
break;
}
default: default:
LOG(ERROR) << "Received unknown signal " << signal; LOG(ERROR) << "Received unknown signal " << signal;
break; break;

View file

@ -1,3 +1,30 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <arpa/inet.h>
#include <cutils/sockets.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <android-base/logging.h> #include <android-base/logging.h>
#include <libsnapshot/snapuserd.h> #include <libsnapshot/snapuserd.h>
#include <libsnapshot/snapuserd_server.h> #include <libsnapshot/snapuserd_server.h>
@ -38,9 +65,9 @@ void SnapuserdServer::Parsemsg(std::string const& msg, const char delim,
// new thread // new thread
void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device) { void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device) {
Snapuserd snapd(cow_device, backing_device); Snapuserd snapd(cow_device, backing_device);
if (snapd.Init()) { if (!snapd.Init()) {
PLOG(ERROR) << "Snapuserd: Init failed"; PLOG(ERROR) << "Snapuserd: Init failed";
exit(EXIT_FAILURE); return;
} }
while (StopRequested() == false) { while (StopRequested() == false) {