Merge "logcat: clean up handling of logd control commands with -f and -L"
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index e7a3ff2..824ee43 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -20,6 +20,7 @@
#include <sys/sysmacros.h>
#include <sys/types.h>
+#include <chrono>
#include <functional>
#include <thread>
@@ -79,14 +80,24 @@
return true;
}
-bool DeviceMapper::DeleteDeviceIfExists(const std::string& name) {
+bool DeviceMapper::DeleteDeviceIfExists(const std::string& name,
+ const std::chrono::milliseconds& timeout_ms) {
if (GetState(name) == DmDeviceState::INVALID) {
return true;
}
- return DeleteDevice(name);
+ return DeleteDevice(name, timeout_ms);
}
-bool DeviceMapper::DeleteDevice(const std::string& name) {
+bool DeviceMapper::DeleteDeviceIfExists(const std::string& name) {
+ return DeleteDeviceIfExists(name, 0ms);
+}
+
+bool DeviceMapper::DeleteDevice(const std::string& name,
+ const std::chrono::milliseconds& timeout_ms) {
+ std::string unique_path;
+ if (!GetDeviceUniquePath(name, &unique_path)) {
+ LOG(ERROR) << "Failed to get unique path for device " << name;
+ }
struct dm_ioctl io;
InitIo(&io, name);
@@ -100,9 +111,23 @@
CHECK(io.flags & DM_UEVENT_GENERATED_FLAG)
<< "Didn't generate uevent for [" << name << "] removal";
+ if (timeout_ms <= std::chrono::milliseconds::zero()) {
+ return true;
+ }
+ if (unique_path.empty()) {
+ return false;
+ }
+ if (!WaitForFileDeleted(unique_path, timeout_ms)) {
+ LOG(ERROR) << "Timeout out waiting for " << unique_path << " to be deleted";
+ return false;
+ }
return true;
}
+bool DeviceMapper::DeleteDevice(const std::string& name) {
+ return DeleteDevice(name, 0ms);
+}
+
static std::string GenerateUuid() {
uuid_t uuid_bytes;
uuid_generate(uuid_bytes);
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index ed2fa83..1695953 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -520,3 +520,27 @@
ASSERT_TRUE(target.Valid());
ASSERT_EQ(target.GetParameterString(), "AES-256-XTS abcdef0123456789 /dev/loop0 0");
}
+
+TEST(libdm, DeleteDeviceWithTimeout) {
+ unique_fd tmp(CreateTempFile("file_1", 4096));
+ ASSERT_GE(tmp, 0);
+ LoopDevice loop(tmp, 10s);
+ ASSERT_TRUE(loop.valid());
+
+ DmTable table;
+ ASSERT_TRUE(table.Emplace<DmTargetLinear>(0, 1, loop.device(), 0));
+ ASSERT_TRUE(table.valid());
+ TempDevice dev("libdm-test-dm-linear", table);
+ ASSERT_TRUE(dev.valid());
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+
+ std::string path;
+ ASSERT_TRUE(dm.GetDmDevicePathByName("libdm-test-dm-linear", &path));
+ ASSERT_EQ(0, access(path.c_str(), F_OK));
+
+ ASSERT_TRUE(dm.DeleteDevice("libdm-test-dm-linear", 5s));
+ ASSERT_EQ(DmDeviceState::INVALID, dm.GetState("libdm-test-dm-linear"));
+ ASSERT_NE(0, access(path.c_str(), F_OK));
+ ASSERT_EQ(ENOENT, errno);
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index e25ce7f..830c5e8 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -90,6 +90,10 @@
// Returns 'true' on success, false otherwise.
bool DeleteDevice(const std::string& name);
bool DeleteDeviceIfExists(const std::string& name);
+ // Removes a device mapper device with the given name and waits for |timeout_ms| milliseconds
+ // for the corresponding block device to be deleted.
+ bool DeleteDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms);
+ bool DeleteDeviceIfExists(const std::string& name, const std::chrono::milliseconds& timeout_ms);
// Fetches and returns the complete state of the underlying device mapper
// device with given name.
diff --git a/fs_mgr/libdm/utility.cpp b/fs_mgr/libdm/utility.cpp
index eccf2fb..f252565 100644
--- a/fs_mgr/libdm/utility.cpp
+++ b/fs_mgr/libdm/utility.cpp
@@ -52,5 +52,15 @@
return WaitForCondition(condition, timeout_ms);
}
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms) {
+ auto condition = [&]() -> WaitResult {
+ if (access(path.c_str(), F_OK) == 0 || errno != ENOENT) {
+ return WaitResult::Wait;
+ }
+ return WaitResult::Done;
+ };
+ return WaitForCondition(condition, timeout_ms);
+}
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libdm/utility.h b/fs_mgr/libdm/utility.h
index f1dce9e..58fa96b 100644
--- a/fs_mgr/libdm/utility.h
+++ b/fs_mgr/libdm/utility.h
@@ -23,6 +23,7 @@
enum class WaitResult { Wait, Done, Fail };
bool WaitForFile(const std::string& path, const std::chrono::milliseconds& timeout_ms);
+bool WaitForFileDeleted(const std::string& path, const std::chrono::milliseconds& timeout_ms);
bool WaitForCondition(const std::function<WaitResult()>& condition,
const std::chrono::milliseconds& timeout_ms);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 1028330..6bf3997 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1181,7 +1181,7 @@
return Error() << "glob pattern '" << glob_pattern << "' failed";
}
std::vector<std::string> configs;
- Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance());
+ Parser parser = CreateServiceOnlyParser(ServiceList::GetInstance(), true);
for (size_t i = 0; i < glob_result.gl_pathc; i++) {
std::string path = glob_result.gl_pathv[i];
// Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
diff --git a/init/init.cpp b/init/init.cpp
index c457de6..6ba64ee 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -121,11 +121,12 @@
}
// parser that only accepts new services
-Parser CreateServiceOnlyParser(ServiceList& service_list) {
+Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex) {
Parser parser;
- parser.AddSectionParser("service", std::make_unique<ServiceParser>(
- &service_list, subcontext.get(), std::nullopt));
+ parser.AddSectionParser("service",
+ std::make_unique<ServiceParser>(&service_list, subcontext.get(),
+ std::nullopt, from_apex));
return parser;
}
diff --git a/init/init.h b/init/init.h
index 0805940..4bbca6f 100644
--- a/init/init.h
+++ b/init/init.h
@@ -29,7 +29,7 @@
namespace init {
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
-Parser CreateServiceOnlyParser(ServiceList& service_list);
+Parser CreateServiceOnlyParser(ServiceList& service_list, bool from_apex);
bool start_waiting_for_property(const char *name, const char *value);
diff --git a/init/reboot.cpp b/init/reboot.cpp
index e9d918e..0e61234 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -797,6 +797,14 @@
if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
return Error() << "Failed to switch to bootstrap namespace";
}
+ // Remove services that were defined in an APEX.
+ ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr<Service>& s) -> bool {
+ if (s->is_from_apex()) {
+ LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX";
+ return true;
+ }
+ return false;
+ });
// Re-enable services
for (const auto& s : were_enabled) {
LOG(INFO) << "Re-enabling service '" << s->name() << "'";
diff --git a/init/service.cpp b/init/service.cpp
index cc97d94..be46585 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -131,13 +131,13 @@
bool Service::is_exec_service_running_ = false;
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
- const std::vector<std::string>& args)
- : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args) {}
+ const std::vector<std::string>& args, bool from_apex)
+ : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args, from_apex) {}
Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
const std::vector<gid_t>& supp_gids, int namespace_flags,
const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
- const std::vector<std::string>& args)
+ const std::vector<std::string>& args, bool from_apex)
: name_(name),
classnames_({"default"}),
flags_(flags),
@@ -155,7 +155,8 @@
"onrestart", {}),
oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
start_order_(0),
- args_(args) {}
+ args_(args),
+ from_apex_(from_apex) {}
void Service::NotifyStateChange(const std::string& new_state) const {
if ((flags_ & SVC_TEMPORARY) != 0) {
@@ -763,7 +764,7 @@
}
return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, namespace_flags, seclabel,
- nullptr, str_args);
+ nullptr, str_args, false);
}
} // namespace init
diff --git a/init/service.h b/init/service.h
index f842b3c..cf3f0c2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -65,11 +65,12 @@
public:
Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
- const std::vector<std::string>& args);
+ const std::vector<std::string>& args, bool from_apex = false);
Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
const std::vector<gid_t>& supp_gids, int namespace_flags, const std::string& seclabel,
- Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
+ Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args,
+ bool from_apex = false);
static Result<std::unique_ptr<Service>> MakeTemporaryOneshotService(
const std::vector<std::string>& args);
@@ -128,6 +129,7 @@
const std::vector<std::string>& args() const { return args_; }
bool is_updatable() const { return updatable_; }
bool is_post_data() const { return post_data_; }
+ bool is_from_apex() const { return from_apex_; }
private:
void NotifyStateChange(const std::string& new_state) const;
@@ -199,6 +201,8 @@
bool running_at_post_data_reset_ = false;
std::optional<std::string> on_failure_reboot_target_;
+
+ bool from_apex_ = false;
};
} // namespace init
diff --git a/init/service_list.h b/init/service_list.h
index ee2c702..1838624 100644
--- a/init/service_list.h
+++ b/init/service_list.h
@@ -34,6 +34,11 @@
void AddService(std::unique_ptr<Service> service);
void RemoveService(const Service& svc);
+ template <class UnaryPredicate>
+ void RemoveServiceIf(UnaryPredicate predicate) {
+ services_.erase(std::remove_if(services_.begin(), services_.end(), predicate),
+ services_.end());
+ }
template <typename T, typename F = decltype(&Service::name)>
Service* FindService(T value, F function = &Service::name) const {
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 154d1dd..1d431e3 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -569,7 +569,7 @@
}
}
- service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
+ service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args, from_apex_);
return {};
}
diff --git a/init/service_parser.h b/init/service_parser.h
index b1281f5..7bb0cc0 100644
--- a/init/service_parser.h
+++ b/init/service_parser.h
@@ -31,11 +31,13 @@
public:
ServiceParser(
ServiceList* service_list, Subcontext* subcontext,
- const std::optional<InterfaceInheritanceHierarchyMap>& interface_inheritance_hierarchy)
+ const std::optional<InterfaceInheritanceHierarchyMap>& interface_inheritance_hierarchy,
+ bool from_apex = false)
: service_list_(service_list),
subcontext_(subcontext),
interface_inheritance_hierarchy_(interface_inheritance_hierarchy),
- service_(nullptr) {}
+ service_(nullptr),
+ from_apex_(from_apex) {}
Result<void> ParseSection(std::vector<std::string>&& args, const std::string& filename,
int line) override;
Result<void> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -89,6 +91,7 @@
std::optional<InterfaceInheritanceHierarchyMap> interface_inheritance_hierarchy_;
std::unique_ptr<Service> service_;
std::string filename_;
+ bool from_apex_ = false;
};
} // namespace init
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 250e600..0ab68db 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -139,6 +139,9 @@
if (start == info->start && end == info->end && flags == info->flags && *name == info->name) {
// No need to check
search_map_idx = old_map_idx + 1;
+ if (new_map_idx + 1 < maps_.size()) {
+ maps_[new_map_idx + 1]->prev_map = info.get();
+ }
maps_[new_map_idx] = nullptr;
total_entries--;
break;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 782fb92..ff68734 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -669,6 +669,7 @@
# Wait for apexd to finish activating APEXes before starting more processes.
wait_for_prop apexd.status ready
parse_apex_configs
+ exec_start derive_sdk
init_user0