Merge "libsnapshot:snapuserd: Handle signals"
This commit is contained in:
commit
c81477c5e4
8 changed files with 185 additions and 43 deletions
|
@ -65,7 +65,7 @@ class Snapuserd final {
|
|||
backing_store_device_(in_backing_store_device),
|
||||
metadata_read_done_(false) {}
|
||||
|
||||
int Init();
|
||||
bool Init();
|
||||
int Run();
|
||||
int ReadDmUserHeader();
|
||||
int WriteDmUserPayload(size_t size);
|
||||
|
|
|
@ -14,22 +14,8 @@
|
|||
|
||||
#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 <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
#include <libsnapshot/snapuserd_server.h>
|
||||
|
||||
namespace android {
|
||||
|
@ -34,12 +36,17 @@ class Daemon {
|
|||
|
||||
private:
|
||||
bool is_running_;
|
||||
std::unique_ptr<struct pollfd> poll_fd_;
|
||||
// Signal mask used with ppoll()
|
||||
sigset_t signal_mask_;
|
||||
|
||||
Daemon();
|
||||
Daemon(Daemon const&) = delete;
|
||||
void operator=(Daemon const&) = delete;
|
||||
|
||||
SnapuserdServer server_;
|
||||
void MaskAllSignalsExceptIntAndTerm();
|
||||
void MaskAllSignals();
|
||||
static void SignalHandler(int signal);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,18 +14,6 @@
|
|||
|
||||
#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 <cstring>
|
||||
#include <functional>
|
||||
|
@ -89,6 +77,7 @@ class SnapuserdServer : public Stoppable {
|
|||
android::base::unique_fd sockfd_;
|
||||
bool terminating_;
|
||||
std::vector<std::unique_ptr<Client>> clients_vec_;
|
||||
|
||||
void ThreadStart(std::string cow_device, std::string backing_device) override;
|
||||
void ShutdownThreads();
|
||||
DaemonOperations Resolveop(std::string& input);
|
||||
|
@ -100,8 +89,6 @@ class SnapuserdServer : public Stoppable {
|
|||
bool IsTerminating() { return terminating_; }
|
||||
|
||||
public:
|
||||
~SnapuserdServer() { clients_vec_.clear(); }
|
||||
|
||||
SnapuserdServer() { terminating_ = false; }
|
||||
|
||||
int Start(std::string socketname);
|
||||
|
@ -109,6 +96,7 @@ class SnapuserdServer : public Stoppable {
|
|||
int Receivemsg(int fd);
|
||||
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
|
||||
|
|
|
@ -485,17 +485,17 @@ int Snapuserd::WriteDmUserPayload(size_t 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));
|
||||
if (backing_store_fd_ < 0) {
|
||||
LOG(ERROR) << "Open Failed: " << backing_store_device_;
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
cow_fd_.reset(open(cow_device_.c_str(), O_RDWR));
|
||||
if (cow_fd_ < 0) {
|
||||
LOG(ERROR) << "Open Failed: " << cow_device_;
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string str(cow_device_);
|
||||
|
@ -509,7 +509,7 @@ int Snapuserd::Init() {
|
|||
std::string uuid;
|
||||
if (!dm.GetDmDeviceUuidByName(device_name, &uuid)) {
|
||||
LOG(ERROR) << "Unable to find UUID for " << cow_device_;
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "UUID: " << uuid;
|
||||
|
@ -518,7 +518,7 @@ int Snapuserd::Init() {
|
|||
ctrl_fd_.reset(open(t.control_path().c_str(), O_RDWR));
|
||||
if (ctrl_fd_ < 0) {
|
||||
LOG(ERROR) << "Unable to open " << t.control_path();
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
bufsink_.Initialize(buf_size);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Snapuserd::Run() {
|
||||
|
@ -601,6 +601,11 @@ int Snapuserd::Run() {
|
|||
ret = ReadData(chunk + num_chunks_read, read_size);
|
||||
if (ret < 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -622,7 +627,7 @@ int Snapuserd::Run() {
|
|||
}
|
||||
|
||||
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
|
||||
// completed. If dm-user routes the WRITE IO, we need to clear
|
||||
// in-memory data structures representing those exception
|
||||
|
|
|
@ -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 <libsnapshot/snapuserd_client.h>
|
||||
|
||||
|
@ -67,6 +97,37 @@ int SnapuserdClient::Sendmsg(const char* msg, size_t size) {
|
|||
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() {
|
||||
char msg[PACKET_SIZE];
|
||||
std::string msgStr("fail");
|
||||
|
@ -82,6 +143,7 @@ std::string SnapuserdClient::Receivemsg() {
|
|||
msgStr = msg;
|
||||
return msgStr;
|
||||
}
|
||||
#endif
|
||||
|
||||
int SnapuserdClient::StopSnapuserd(bool firstStageDaemon) {
|
||||
if (firstStageDaemon) {
|
||||
|
|
|
@ -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 <libsnapshot/snapuserd_daemon.h>
|
||||
|
||||
|
@ -16,11 +32,27 @@ int Daemon::StartServer(std::string socketname) {
|
|||
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() {
|
||||
is_running_ = true;
|
||||
// TODO: Mask other signals - Bug 168258493
|
||||
signal(SIGINT, Daemon::SignalHandler);
|
||||
signal(SIGTERM, Daemon::SignalHandler);
|
||||
}
|
||||
|
||||
bool Daemon::IsRunning() {
|
||||
|
@ -28,10 +60,41 @@ bool Daemon::IsRunning() {
|
|||
}
|
||||
|
||||
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()) {
|
||||
if (server_.AcceptClient() == static_cast<int>(DaemonOperations::STOP)) {
|
||||
Daemon::Instance().is_running_ = false;
|
||||
int ret = ppoll(poll_fd_.get(), 1, nullptr, &signal_mask_);
|
||||
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;
|
||||
break;
|
||||
}
|
||||
case SIGPIPE: {
|
||||
LOG(ERROR) << "Received SIGPIPE signal";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(ERROR) << "Received unknown signal " << signal;
|
||||
break;
|
||||
|
|
|
@ -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 <libsnapshot/snapuserd.h>
|
||||
#include <libsnapshot/snapuserd_server.h>
|
||||
|
@ -38,9 +65,9 @@ void SnapuserdServer::Parsemsg(std::string const& msg, const char delim,
|
|||
// new thread
|
||||
void SnapuserdServer::ThreadStart(std::string cow_device, std::string backing_device) {
|
||||
Snapuserd snapd(cow_device, backing_device);
|
||||
if (snapd.Init()) {
|
||||
if (!snapd.Init()) {
|
||||
PLOG(ERROR) << "Snapuserd: Init failed";
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
while (StopRequested() == false) {
|
||||
|
|
Loading…
Reference in a new issue