Merge "Revert "Fix non-existent module error""
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 1462cc9..d6fd513 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -521,13 +521,13 @@
}
// Enable casefold if needed.
-static void tune_casefold(const std::string& blk_device, const struct ext4_super_block* sb,
- int* fs_stat) {
+static void tune_casefold(const std::string& blk_device, const FstabEntry& entry,
+ const struct ext4_super_block* sb, int* fs_stat) {
bool has_casefold = (sb->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_CASEFOLD)) != 0;
bool wants_casefold =
android::base::GetBoolProperty("external_storage.casefold.enabled", false);
- if (!wants_casefold || has_casefold) return;
+ if (entry.mount_point != "data" || !wants_casefold || has_casefold ) return;
std::string casefold_support;
if (!android::base::ReadFileToString(SYSFS_EXT4_CASEFOLD, &casefold_support)) {
@@ -696,7 +696,7 @@
tune_reserved_size(blk_device, entry, &sb, &fs_stat);
tune_encrypt(blk_device, entry, &sb, &fs_stat);
tune_verity(blk_device, entry, &sb, &fs_stat);
- tune_casefold(blk_device, &sb, &fs_stat);
+ tune_casefold(blk_device, entry, &sb, &fs_stat);
tune_metadata_csum(blk_device, entry, &sb, &fs_stat);
}
}
@@ -976,6 +976,19 @@
}
}
+static void set_type_property(int status) {
+ switch (status) {
+ case FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED:
+ SetProperty("ro.crypto.type", "block");
+ break;
+ case FS_MGR_MNTALL_DEV_FILE_ENCRYPTED:
+ case FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED:
+ case FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION:
+ SetProperty("ro.crypto.type", "file");
+ break;
+ }
+}
+
static bool call_vdc(const std::vector<std::string>& args, int* ret) {
std::vector<char const*> argv;
argv.emplace_back("/system/bin/vdc");
@@ -1366,6 +1379,7 @@
avb_handle = AvbHandle::Open();
if (!avb_handle) {
LERROR << "Failed to open AvbHandle";
+ set_type_property(encryptable);
return FS_MGR_MNTALL_FAIL;
}
}
@@ -1422,6 +1436,7 @@
attempted_entry.mount_point},
nullptr)) {
LERROR << "Encryption failed";
+ set_type_property(encryptable);
return FS_MGR_MNTALL_FAIL;
}
}
@@ -1519,6 +1534,8 @@
}
}
+ set_type_property(encryptable);
+
#if ALLOW_ADBD_DISABLE_VERITY == 1 // "userdebug" build
fs_mgr_overlayfs_mount_all(fstab);
#endif
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 04a99a3..e95efc0 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -693,7 +693,7 @@
InitAnimation();
- ret = CreateDisplaySurface(batt_anim_.fail_file.c_str(), &surf_unknown_);
+ ret = CreateDisplaySurface(batt_anim_.fail_file, &surf_unknown_);
if (ret < 0) {
LOGE("Cannot load custom battery_fail image. Reverting to built in: %d\n", ret);
ret = CreateDisplaySurface((system_animation_root + "charger/battery_fail.png"s).c_str(),
@@ -708,7 +708,7 @@
int scale_count;
int scale_fps; // Not in use (charger/battery_scale doesn't have FPS text
// chunk). We are using hard-coded frame.disp_time instead.
- ret = CreateMultiDisplaySurface(batt_anim_.animation_file.c_str(), &scale_count, &scale_fps,
+ ret = CreateMultiDisplaySurface(batt_anim_.animation_file, &scale_count, &scale_fps,
&scale_frames);
if (ret < 0) {
LOGE("Cannot load battery_scale image\n");
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 0b456e7..f5de1ad 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -570,7 +570,6 @@
trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
}
SetProperty("ro.crypto.state", "encrypted");
- SetProperty("ro.crypto.type", "block");
ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
return {};
} else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
@@ -595,7 +594,6 @@
return Error() << "FscryptInstallKeyring() failed";
}
SetProperty("ro.crypto.state", "encrypted");
- SetProperty("ro.crypto.type", "file");
// Although encrypted, we have device key, so we do not need to
// do anything different from the nonencrypted case.
@@ -606,7 +604,6 @@
return Error() << "FscryptInstallKeyring() failed";
}
SetProperty("ro.crypto.state", "encrypted");
- SetProperty("ro.crypto.type", "file");
// Although encrypted, vold has already set the device up, so we do not need to
// do anything different from the nonencrypted case.
@@ -617,7 +614,6 @@
return Error() << "FscryptInstallKeyring() failed";
}
SetProperty("ro.crypto.state", "encrypted");
- SetProperty("ro.crypto.type", "file");
// Although encrypted, vold has already set the device up, so we do not need to
// do anything different from the nonencrypted case.
diff --git a/libcutils/uevent.cpp b/libcutils/uevent.cpp
index bf244d2..40bbd5c 100644
--- a/libcutils/uevent.cpp
+++ b/libcutils/uevent.cpp
@@ -101,7 +101,7 @@
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
- addr.nl_pid = getpid();
+ addr.nl_pid = 0;
addr.nl_groups = 0xffffffff;
s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
diff --git a/liblog/event_tag_map.cpp b/liblog/event_tag_map.cpp
index 2c0156e..85556e8 100644
--- a/liblog/event_tag_map.cpp
+++ b/liblog/event_tag_map.cpp
@@ -31,84 +31,13 @@
#include <unordered_map>
#include <log/event_tag_map.h>
-#include <log/log_properties.h>
#include <private/android_logger.h>
#include <utils/FastStrcmp.h>
#include <utils/RWLock.h>
-#include "logd_reader.h"
-
#define OUT_TAG "EventTagMap"
-class MapString {
- private:
- const std::string* alloc; // HAS-AN
- const std::string_view str; // HAS-A
-
- public:
- operator const std::string_view() const {
- return str;
- }
-
- const char* data() const {
- return str.data();
- }
- size_t length() const {
- return str.length();
- }
-
- bool operator==(const MapString& rval) const {
- if (length() != rval.length()) return false;
- if (length() == 0) return true;
- return fastcmp<strncmp>(data(), rval.data(), length()) == 0;
- }
- bool operator!=(const MapString& rval) const {
- return !(*this == rval);
- }
-
- MapString(const char* str, size_t len) : alloc(NULL), str(str, len) {
- }
- explicit MapString(const std::string& str)
- : alloc(new std::string(str)), str(alloc->data(), alloc->length()) {
- }
- MapString(MapString&& rval) noexcept
- : alloc(rval.alloc), str(rval.data(), rval.length()) {
- rval.alloc = NULL;
- }
- explicit MapString(const MapString& rval)
- : alloc(rval.alloc ? new std::string(*rval.alloc) : NULL),
- str(alloc ? alloc->data() : rval.data(), rval.length()) {
- }
-
- ~MapString() {
- if (alloc) delete alloc;
- }
-};
-
-// Hash for MapString
-template <>
-struct std::hash<MapString>
- : public std::unary_function<const MapString&, size_t> {
- size_t operator()(const MapString& __t) const noexcept {
- if (!__t.length()) return 0;
- return std::hash<std::string_view>()(std::string_view(__t));
- }
-};
-
-typedef std::pair<MapString, MapString> TagFmt;
-
-template <>
-struct std::hash<TagFmt> : public std::unary_function<const TagFmt&, size_t> {
- size_t operator()(const TagFmt& __t) const noexcept {
- // Tag is typically unique. Will cost us an extra 100ns for the
- // unordered_map lookup if we instead did a hash that combined
- // both of tag and fmt members, e.g.:
- //
- // return std::hash<MapString>()(__t.first) ^
- // std::hash<MapString>()(__t.second);
- return std::hash<MapString>()(__t.first);
- }
-};
+typedef std::pair<std::string_view, std::string_view> TagFmt;
// Map
struct EventTagMap {
@@ -119,8 +48,7 @@
private:
std::unordered_map<uint32_t, TagFmt> Idx2TagFmt;
- std::unordered_map<TagFmt, uint32_t> TagFmt2Idx;
- std::unordered_map<MapString, uint32_t> Tag2Idx;
+ std::unordered_map<std::string_view, uint32_t> Tag2Idx;
// protect unordered sets
android::RWLock rwlock;
@@ -132,7 +60,6 @@
~EventTagMap() {
Idx2TagFmt.clear();
- TagFmt2Idx.clear();
Tag2Idx.clear();
for (size_t which = 0; which < NUM_MAPS; ++which) {
if (mapAddr[which]) {
@@ -144,8 +71,7 @@
bool emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool verbose = false);
const TagFmt* find(uint32_t tag) const;
- int find(TagFmt&& tagfmt) const;
- int find(MapString&& tag) const;
+ int find(std::string_view tag) const;
};
bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt,
@@ -156,8 +82,7 @@
":%.*s:%.*s)\n";
android::RWLock::AutoWLock writeLock(rwlock);
{
- std::unordered_map<uint32_t, TagFmt>::const_iterator it;
- it = Idx2TagFmt.find(tag);
+ auto it = Idx2TagFmt.find(tag);
if (it != Idx2TagFmt.end()) {
if (verbose) {
fprintf(stderr, errorFormat, it->first, (int)it->second.first.length(),
@@ -173,25 +98,7 @@
}
{
- std::unordered_map<TagFmt, uint32_t>::const_iterator it;
- it = TagFmt2Idx.find(tagfmt);
- if (it != TagFmt2Idx.end()) {
- if (verbose) {
- fprintf(stderr, errorFormat, it->second, (int)it->first.first.length(),
- it->first.first.data(), (int)it->first.second.length(),
- it->first.second.data(), tag, (int)tagfmt.first.length(),
- tagfmt.first.data(), (int)tagfmt.second.length(),
- tagfmt.second.data());
- }
- ret = false;
- } else {
- TagFmt2Idx.emplace(std::make_pair(tagfmt, tag));
- }
- }
-
- {
- std::unordered_map<MapString, uint32_t>::const_iterator it;
- it = Tag2Idx.find(tagfmt.first);
+ auto it = Tag2Idx.find(tagfmt.first);
if (!tagfmt.second.length() && (it != Tag2Idx.end())) {
Tag2Idx.erase(it);
it = Tag2Idx.end();
@@ -205,25 +112,15 @@
}
const TagFmt* EventTagMap::find(uint32_t tag) const {
- std::unordered_map<uint32_t, TagFmt>::const_iterator it;
android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
- it = Idx2TagFmt.find(tag);
+ auto it = Idx2TagFmt.find(tag);
if (it == Idx2TagFmt.end()) return NULL;
return &(it->second);
}
-int EventTagMap::find(TagFmt&& tagfmt) const {
- std::unordered_map<TagFmt, uint32_t>::const_iterator it;
+int EventTagMap::find(std::string_view tag) const {
android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
- it = TagFmt2Idx.find(std::move(tagfmt));
- if (it == TagFmt2Idx.end()) return -1;
- return it->second;
-}
-
-int EventTagMap::find(MapString&& tag) const {
- std::unordered_map<MapString, uint32_t>::const_iterator it;
- android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock));
- it = Tag2Idx.find(std::move(tag));
+ auto it = Tag2Idx.find(std::move(tag));
if (it == Tag2Idx.end()) return -1;
return it->second;
}
@@ -241,29 +138,20 @@
// successful return, it will be pointing to the last character in the
// tag line (i.e. the character before the start of the next line).
//
-// lineNum = 0 removes verbose comments and requires us to cache the
-// content rather than make direct raw references since the content
-// will disappear after the call. A non-zero lineNum means we own the
-// data and it will outlive the call.
-//
// Returns 0 on success, nonzero on failure.
-static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) {
+static int scanTagLine(EventTagMap* map, const char*& pData, int line_num) {
char* ep;
unsigned long val = strtoul(pData, &ep, 10);
const char* cp = ep;
if (cp == pData) {
- if (lineNum) {
- fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", lineNum);
- }
+ fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", line_num);
errno = EINVAL;
return -1;
}
uint32_t tagIndex = val;
if (tagIndex != val) {
- if (lineNum) {
- fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", lineNum);
- }
+ fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", line_num);
errno = ERANGE;
return -1;
}
@@ -272,9 +160,7 @@
}
if (*cp == '\n') {
- if (lineNum) {
- fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", lineNum);
- }
+ fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", line_num);
errno = EINVAL;
return -1;
}
@@ -284,10 +170,7 @@
size_t tagLen = cp - tag;
if (!isspace(*cp)) {
- if (lineNum) {
- fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp,
- lineNum);
- }
+ fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp, line_num);
errno = EINVAL;
return -1;
}
@@ -317,25 +200,15 @@
while (*cp && (*cp != '\n')) ++cp;
#ifdef DEBUG
- fprintf(stderr, "%d: %p: %.*s\n", lineNum, tag, (int)(cp - pData), pData);
+ fprintf(stderr, "%d: %p: %.*s\n", line_num, tag, (int)(cp - pData), pData);
#endif
pData = cp;
- if (lineNum) {
- if (map->emplaceUnique(tagIndex,
- TagFmt(std::make_pair(MapString(tag, tagLen),
- MapString(fmt, fmtLen))),
- verbose)) {
- return 0;
- }
- } else {
- // cache
- if (map->emplaceUnique(
- tagIndex,
- TagFmt(std::make_pair(MapString(std::string(tag, tagLen)),
- MapString(std::string(fmt, fmtLen)))))) {
- return 0;
- }
+ if (map->emplaceUnique(
+ tagIndex,
+ TagFmt(std::make_pair(std::string_view(tag, tagLen), std::string_view(fmt, fmtLen))),
+ verbose)) {
+ return 0;
}
errno = EMLINK;
return -1;
@@ -491,57 +364,10 @@
if (map) delete map;
}
-// Cache miss, go to logd to acquire a public reference.
-// Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map?
-static const TagFmt* __getEventTag([[maybe_unused]] EventTagMap* map, unsigned int tag) {
- // call event tag service to arrange for a new tag
- char* buf = NULL;
- // Can not use android::base::StringPrintf, asprintf + free instead.
- static const char command_template[] = "getEventTag id=%u";
- int ret = asprintf(&buf, command_template, tag);
- if (ret > 0) {
- // Add some buffer margin for an estimate of the full return content.
- size_t size =
- ret - strlen(command_template) +
- strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?");
- if (size > (size_t)ret) {
- char* np = static_cast<char*>(realloc(buf, size));
- if (np) {
- buf = np;
- } else {
- size = ret;
- }
- } else {
- size = ret;
- }
-#ifdef __ANDROID__
- // Ask event log tag service for an existing entry
- if (SendLogdControlMessage(buf, size) >= 0) {
- buf[size - 1] = '\0';
- char* ep;
- unsigned long val = strtoul(buf, &ep, 10); // return size
- const char* cp = ep;
- if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK
- ++cp;
- if (!scanTagLine(map, cp, 0)) {
- free(buf);
- return map->find(tag);
- }
- }
- }
-#endif
- free(buf);
- }
- return NULL;
-}
-
// Look up an entry in the map.
const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsigned int tag) {
if (len) *len = 0;
const TagFmt* str = map->find(tag);
- if (!str) {
- str = __getEventTag(const_cast<EventTagMap*>(map), tag);
- }
if (!str) return NULL;
if (len) *len = str->first.length();
return str->first.data();
@@ -551,83 +377,8 @@
const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag) {
if (len) *len = 0;
const TagFmt* str = map->find(tag);
- if (!str) {
- str = __getEventTag(const_cast<EventTagMap*>(map), tag);
- }
if (!str) return NULL;
if (len) *len = str->second.length();
return str->second.data();
}
-// Look up tagname, generate one if necessary, and return a tag
-int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio) {
- const char* ep = endOfTag(tagname);
- size_t len = ep - tagname;
- if (!len || *ep) {
- errno = EINVAL;
- return -1;
- }
-
- if ((prio != ANDROID_LOG_UNKNOWN) && (prio < ANDROID_LOG_SILENT) &&
- !__android_log_is_loggable_len(prio, tagname, len,
- __android_log_is_debuggable()
- ? ANDROID_LOG_VERBOSE
- : ANDROID_LOG_DEBUG)) {
- errno = EPERM;
- return -1;
- }
-
- if (!format) format = "";
- ssize_t fmtLen = strlen(format);
- int ret = map->find(TagFmt(
- std::make_pair(MapString(tagname, len), MapString(format, fmtLen))));
- if (ret != -1) return ret;
-
- // call event tag service to arrange for a new tag
- char* buf = NULL;
- // Can not use android::base::StringPrintf, asprintf + free instead.
- static const char command_template[] = "getEventTag name=%s format=\"%s\"";
- ret = asprintf(&buf, command_template, tagname, format);
- if (ret > 0) {
- // Add some buffer margin for an estimate of the full return content.
- char* cp;
- size_t size =
- ret - strlen(command_template) +
- strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?");
- if (size > (size_t)ret) {
- cp = static_cast<char*>(realloc(buf, size));
- if (cp) {
- buf = cp;
- } else {
- size = ret;
- }
- } else {
- size = ret;
- }
-#ifdef __ANDROID__
- // Ask event log tag service for an allocation
- if (SendLogdControlMessage(buf, size) >= 0) {
- buf[size - 1] = '\0';
- unsigned long val = strtoul(buf, &cp, 10); // return size
- if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK
- val = strtoul(cp + 1, &cp, 10); // allocated tag number
- if ((val > 0) && (val < UINT32_MAX) && (*cp == '\t')) {
- free(buf);
- ret = val;
- // cache
- map->emplaceUnique(ret, TagFmt(std::make_pair(
- MapString(std::string(tagname, len)),
- MapString(std::string(format, fmtLen)))));
- return ret;
- }
- }
- }
-#endif
- free(buf);
- }
-
- // Hail Mary
- ret = map->find(MapString(tagname, len));
- if (ret == -1) errno = ESRCH;
- return ret;
-}
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 4d0ebf9..de49fbf 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -53,12 +53,6 @@
const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len,
unsigned int tag);
-/*
- * Look up tagname, generate one if necessary, and return a tag
- */
-int android_lookupEventTagNum(EventTagMap* map, const char* tagname,
- const char* format, int prio);
-
#ifdef __cplusplus
}
#endif
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 8beb679..f8d5ef0 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -89,6 +89,5 @@
android_log_processLogBuffer;
android_log_read_next;
android_log_write_list_buffer;
- android_lookupEventTagNum;
create_android_log_parser;
};
diff --git a/liblog/logd_writer.cpp b/liblog/logd_writer.cpp
index a230749..f5d19ca 100644
--- a/liblog/logd_writer.cpp
+++ b/liblog/logd_writer.cpp
@@ -59,8 +59,7 @@
return;
}
- int new_socket =
- TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+ int new_socket = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0));
if (new_socket <= 0) {
return;
}
@@ -91,8 +90,6 @@
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
- static atomic_int dropped;
- static atomic_int droppedSecurity;
GetSocket();
@@ -110,6 +107,7 @@
return 0;
}
+ header.id = logId;
header.tid = gettid();
header.realtime.tv_sec = ts->tv_sec;
header.realtime.tv_nsec = ts->tv_nsec;
@@ -117,44 +115,6 @@
newVec[0].iov_base = (unsigned char*)&header;
newVec[0].iov_len = sizeof(header);
- int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
- if (snapshot) {
- android_log_event_int_t buffer;
-
- header.id = LOG_ID_SECURITY;
- buffer.header.tag = LIBLOG_LOG_TAG;
- buffer.payload.type = EVENT_TYPE_INT;
- buffer.payload.data = snapshot;
-
- newVec[headerLength].iov_base = &buffer;
- newVec[headerLength].iov_len = sizeof(buffer);
-
- ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
- if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
- }
- }
- snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
- if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
- ANDROID_LOG_VERBOSE)) {
- android_log_event_int_t buffer;
-
- header.id = LOG_ID_EVENTS;
- buffer.header.tag = LIBLOG_LOG_TAG;
- buffer.payload.type = EVENT_TYPE_INT;
- buffer.payload.data = snapshot;
-
- newVec[headerLength].iov_base = &buffer;
- newVec[headerLength].iov_len = sizeof(buffer);
-
- ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, 2));
- if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
- }
- }
-
- header.id = logId;
-
for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) {
newVec[i].iov_base = vec[i - headerLength].iov_base;
payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len;
@@ -168,11 +128,8 @@
}
}
- // The write below could be lost, but will never block.
- // EAGAIN occurs if logd is overloaded, other errors indicate that something went wrong with
- // the connection, so we reset it and try again.
ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
- if (ret < 0 && errno != EAGAIN) {
+ if (ret < 0) {
LogdConnect();
ret = TEMP_FAILURE_RETRY(writev(logd_socket, newVec, i));
@@ -182,14 +139,5 @@
ret = -errno;
}
- if (ret > (ssize_t)sizeof(header)) {
- ret -= sizeof(header);
- } else if (ret < 0) {
- atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
- if (logId == LOG_ID_SECURITY) {
- atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed);
- }
- }
-
return ret;
}
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 3bd5cf2..d2f12d6 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -879,30 +879,6 @@
}
BENCHMARK(BM_lookupEventFormat);
-/*
- * Measure the time it takes for android_lookupEventTagNum plus above
- */
-static void BM_lookupEventTagNum(benchmark::State& state) {
- prechargeEventMap();
-
- std::unordered_set<uint32_t>::const_iterator it = set.begin();
-
- while (state.KeepRunning()) {
- size_t len;
- const char* name = android_lookupEventTag_len(map, &len, (*it));
- std::string Name(name, len);
- const char* format = android_lookupEventFormat_len(map, &len, (*it));
- std::string Format(format, len);
- state.ResumeTiming();
- android_lookupEventTagNum(map, Name.c_str(), Format.c_str(),
- ANDROID_LOG_UNKNOWN);
- state.PauseTiming();
- ++it;
- if (it == set.end()) it = set.begin();
- }
-}
-BENCHMARK(BM_lookupEventTagNum);
-
// Must be functionally identical to liblog internal SendLogdControlMessage()
static void send_to_control(char* buf, size_t len) {
int sock =
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index fbc3d7a..c49d87b 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -2768,20 +2768,3 @@
#endif
}
#endif // ENABLE_FLAKY_TESTS
-
-TEST(liblog, android_lookupEventTagNum) {
-#ifdef __ANDROID__
- EventTagMap* map = android_openEventTagMap(NULL);
- EXPECT_TRUE(NULL != map);
- std::string Name = android::base::StringPrintf("a%d", getpid());
- int tag = android_lookupEventTagNum(map, Name.c_str(), "(new|1)",
- ANDROID_LOG_UNKNOWN);
- android_closeEventTagMap(map);
- if (tag == -1) system("tail -3 /dev/event-log-tags >&2");
- EXPECT_NE(-1, tag);
- EXPECT_NE(0, tag);
- EXPECT_GT(UINT32_MAX, (unsigned)tag);
-#else
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 2d867cd..b904632 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -75,7 +75,7 @@
frame->rel_pc = dex_pc - info->start;
} else {
frame->rel_pc = dex_pc;
- return;
+ warnings_ |= WARNING_DEX_PC_NOT_IN_MAP;
}
if (!resolve_names_) {
@@ -142,6 +142,7 @@
void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
const std::vector<std::string>* map_suffixes_to_ignore) {
frames_.clear();
+ warnings_ = WARNING_NONE;
last_error_.code = ERROR_NONE;
last_error_.address = 0;
elf_from_memory_not_file_ = false;
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
index 72ec454..66fefe7 100644
--- a/libunwindstack/include/unwindstack/Error.h
+++ b/libunwindstack/include/unwindstack/Error.h
@@ -21,6 +21,13 @@
namespace unwindstack {
+// A bit map of warnings, multiple warnings can be set at the same time.
+enum WarningCode : uint64_t {
+ WARNING_NONE = 0,
+ WARNING_DEX_PC_NOT_IN_MAP = 0x1, // A dex pc was found, but it doesn't exist
+ // in any valid map.
+};
+
enum ErrorCode : uint8_t {
ERROR_NONE, // No error.
ERROR_MEMORY_INVALID, // Memory read failed.
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 4d49f23..a974b63 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -113,6 +113,7 @@
ErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
+ uint64_t warnings() { return warnings_; }
// Builds a frame for symbolization using the maps from this unwinder. The
// constructed frame contains just enough information to be used to symbolize
@@ -141,6 +142,7 @@
// file. This is only true if there is an actual file backing up the elf.
bool elf_from_memory_not_file_ = false;
ErrorData last_error_;
+ uint64_t warnings_;
};
class UnwinderFromPid : public Unwinder {
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index dd33aa9..d10af2f 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -168,6 +168,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -233,6 +234,7 @@
unwinder.SetResolveNames(false);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -293,6 +295,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -323,6 +326,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -353,6 +357,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -384,6 +389,7 @@
unwinder.SetEmbeddedSoname(false);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -421,6 +427,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -454,6 +461,7 @@
Unwinder unwinder(20, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(20U, unwinder.NumFrames());
@@ -497,6 +505,7 @@
std::vector<std::string> skip_libs{"libunwind.so", "libanother.so"};
unwinder.Unwind(&skip_libs);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -559,6 +568,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -607,6 +617,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -627,6 +638,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -642,6 +654,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -679,6 +692,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -745,6 +759,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -795,6 +810,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -843,6 +859,7 @@
std::vector<std::string> skip_names{"libanother.so"};
unwinder.Unwind(&skip_names);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(0U, unwinder.NumFrames());
@@ -866,6 +883,7 @@
std::vector<std::string> suffixes{"oat"};
unwinder.Unwind(nullptr, &suffixes);
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -925,6 +943,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -984,6 +1003,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -1028,6 +1048,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -1072,6 +1093,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(2U, unwinder.NumFrames());
@@ -1119,6 +1141,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(3U, unwinder.NumFrames());
@@ -1178,6 +1201,7 @@
Unwinder unwinder(1, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -1208,6 +1232,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_TRUE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -1238,6 +1263,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -1268,6 +1294,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
@@ -1298,6 +1325,7 @@
Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
unwinder.Unwind();
EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+ EXPECT_EQ(WARNING_NONE, unwinder.warnings());
EXPECT_FALSE(unwinder.elf_from_memory_not_file());
ASSERT_EQ(1U, unwinder.NumFrames());
diff --git a/libutils/include/utils/Debug.h b/libutils/include/utils/Debug.h
index 96bd70e..c3b9026 100644
--- a/libutils/include/utils/Debug.h
+++ b/libutils/include/utils/Debug.h
@@ -14,27 +14,9 @@
* limitations under the License.
*/
-#ifndef ANDROID_UTILS_DEBUG_H
-#define ANDROID_UTILS_DEBUG_H
+#pragma once
-#include <stdint.h>
-#include <sys/types.h>
+// Note: new code should use static_assert directly.
-namespace android {
-// ---------------------------------------------------------------------------
-
-#ifdef __cplusplus
-template<bool> struct CompileTimeAssert;
-template<> struct CompileTimeAssert<true> {};
-#define COMPILE_TIME_ASSERT(_exp) \
- template class CompileTimeAssert< (_exp) >;
-#endif
-
-// DO NOT USE: Please use static_assert instead
-#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
- CompileTimeAssert<( _exp )>();
-
-// ---------------------------------------------------------------------------
-} // namespace android
-
-#endif // ANDROID_UTILS_DEBUG_H
+#define COMPILE_TIME_ASSERT static_assert
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE static_assert
diff --git a/libutils/include/utils/Flattenable.h b/libutils/include/utils/Flattenable.h
index 17c5e10..8aa381a 100644
--- a/libutils/include/utils/Flattenable.h
+++ b/libutils/include/utils/Flattenable.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_UTILS_FLATTENABLE_H
-#define ANDROID_UTILS_FLATTENABLE_H
+#pragma once
// DO NOT USE: please use parcelable instead
// This code is deprecated and will not be supported via AIDL code gen. For data
@@ -25,7 +24,6 @@
#include <string.h>
#include <sys/types.h>
#include <utils/Errors.h>
-#include <utils/Debug.h>
#include <type_traits>
@@ -217,5 +215,3 @@
};
} // namespace android
-
-#endif /* ANDROID_UTILS_FLATTENABLE_H */
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 61aa938..0860000 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -1654,48 +1654,6 @@
EXPECT_GE(ret, 0);
EXPECT_TRUE(End_to_End(sync.tagStr, ""));
}
-
- {
- // Invent new entries because existing can not serve
- EventTagMap* map = android_openEventTagMap(nullptr);
- ASSERT_TRUE(nullptr != map);
- static const char name[] = logcat_executable ".descriptive-monotonic";
- int myTag = android_lookupEventTagNum(map, name, "(new|1|s)",
- ANDROID_LOG_UNKNOWN);
- android_closeEventTagMap(map);
- ASSERT_NE(-1, myTag);
-
- const struct tag sync = { (uint32_t)myTag, name };
-
- {
- android_log_event_list ctx(sync.tagNo);
- ctx << (uint32_t)7;
- for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
- EXPECT_GE(ret, 0);
- EXPECT_TRUE(End_to_End(sync.tagStr, "new=7s"));
- }
- {
- android_log_event_list ctx(sync.tagNo);
- ctx << (uint32_t)62;
- for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
- EXPECT_GE(ret, 0);
- EXPECT_TRUE(End_to_End(sync.tagStr, "new=1:02"));
- }
- {
- android_log_event_list ctx(sync.tagNo);
- ctx << (uint32_t)3673;
- for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
- EXPECT_GE(ret, 0);
- EXPECT_TRUE(End_to_End(sync.tagStr, "new=1:01:13"));
- }
- {
- android_log_event_list ctx(sync.tagNo);
- ctx << (uint32_t)(86400 + 7200 + 180 + 58);
- for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
- EXPECT_GE(ret, 0);
- EXPECT_TRUE(End_to_End(sync.tagStr, "new=1d 2:03:58"));
- }
- }
}
static bool reportedSecurity(const char* command) {
diff --git a/logd/SerializedLogBuffer.cpp b/logd/SerializedLogBuffer.cpp
index 65fedb0..5012d3d 100644
--- a/logd/SerializedLogBuffer.cpp
+++ b/logd/SerializedLogBuffer.cpp
@@ -75,6 +75,10 @@
return -EINVAL;
}
+ if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
+ len = LOGGER_ENTRY_MAX_PAYLOAD;
+ }
+
if (!ShouldLog(log_id, msg, len)) {
stats_->AddTotal(log_id, len);
return -EACCES;
@@ -135,33 +139,42 @@
}
}
-bool SerializedLogBuffer::Prune(log_id_t log_id, size_t bytes_to_free, uid_t uid) {
- // Don't prune logs that are newer than the point at which any reader threads are reading from.
- LogReaderThread* oldest = nullptr;
+void SerializedLogBuffer::Prune(log_id_t log_id, size_t bytes_to_free, uid_t uid) {
auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};
- for (const auto& reader_thread : reader_list_->reader_threads()) {
- if (!reader_thread->IsWatching(log_id)) {
- continue;
- }
- if (!oldest || oldest->start() > reader_thread->start() ||
- (oldest->start() == reader_thread->start() &&
- reader_thread->deadline().time_since_epoch().count() != 0)) {
- oldest = reader_thread.get();
- }
- }
auto& log_buffer = logs_[log_id];
auto it = log_buffer.begin();
while (it != log_buffer.end()) {
- if (oldest != nullptr && it->highest_sequence_number() >= oldest->start()) {
- break;
+ for (const auto& reader_thread : reader_list_->reader_threads()) {
+ if (!reader_thread->IsWatching(log_id)) {
+ continue;
+ }
+
+ if (reader_thread->deadline().time_since_epoch().count() != 0) {
+ // Always wake up wrapped readers when pruning. 'Wrapped' readers are an
+ // optimization that allows the reader to wait until logs starting at a specified
+ // time stamp are about to be pruned. This is error-prone however, since if that
+ // timestamp is about to be pruned, the reader is not likely to read the messages
+ // fast enough to not back-up logd. Instead, we can achieve an nearly-as-efficient
+ // but not error-prune batching effect by waking the reader whenever any chunk is
+ // about to be pruned.
+ reader_thread->triggerReader_Locked();
+ }
+
+ // Some readers may be still reading from this log chunk, log a warning that they are
+ // about to lose logs.
+ // TODO: We should forcefully disconnect the reader instead, such that the reader itself
+ // has an indication that they've lost logs.
+ if (reader_thread->start() <= it->highest_sequence_number()) {
+ LOG(WARNING) << "Skipping entries from slow reader, " << reader_thread->name()
+ << ", from LogBuffer::Prune()";
+ }
}
// Increment ahead of time since we're going to erase this iterator from the list.
auto it_to_prune = it++;
- // The sequence number check ensures that all readers have read all logs in this chunk, but
- // they may still hold a reference to the chunk to track their last read log_position.
+ // Readers may have a reference to the chunk to track their last read log_position.
// Notify them to delete the reference.
NotifyReadersOfPrune(log_id, it_to_prune);
@@ -176,42 +189,11 @@
RemoveChunkFromStats(log_id, *it_to_prune);
log_buffer.erase(it_to_prune);
if (buffer_size >= bytes_to_free) {
- return true;
+ return;
}
bytes_to_free -= buffer_size;
}
}
-
- // If we've deleted all buffers without bytes_to_free hitting 0, then we're called by Clear()
- // and should return true.
- if (it == log_buffer.end()) {
- return true;
- }
-
- // Otherwise we are stuck due to a reader, so mitigate it.
- CHECK(oldest != nullptr);
- KickReader(oldest, log_id, bytes_to_free);
- return false;
-}
-
-// If the selected reader is blocking our pruning progress, decide on
-// what kind of mitigation is necessary to unblock the situation.
-void SerializedLogBuffer::KickReader(LogReaderThread* reader, log_id_t id, size_t bytes_to_free) {
- if (bytes_to_free >= max_size_[id]) { // +100%
- // A misbehaving or slow reader is dropped if we hit too much memory pressure.
- LOG(WARNING) << "Kicking blocked reader, " << reader->name()
- << ", from LogBuffer::kickMe()";
- reader->release_Locked();
- } else if (reader->deadline().time_since_epoch().count() != 0) {
- // Allow a blocked WRAP deadline reader to trigger and start reporting the log data.
- reader->triggerReader_Locked();
- } else {
- // Tell slow reader to skip entries to catch up.
- unsigned long prune_rows = bytes_to_free / 300;
- LOG(WARNING) << "Skipping " << prune_rows << " entries from slow reader, " << reader->name()
- << ", from LogBuffer::kickMe()";
- reader->triggerSkip_Locked(id, prune_rows);
- }
}
std::unique_ptr<FlushToState> SerializedLogBuffer::CreateFlushToState(uint64_t start,
@@ -252,12 +234,18 @@
}
}
+ // We copy the log entry such that we can flush it without the lock. We never block pruning
+ // waiting for this Flush() to complete.
+ constexpr size_t kMaxEntrySize = sizeof(*entry) + LOGGER_ENTRY_MAX_PAYLOAD + 1;
+ unsigned char entry_copy[kMaxEntrySize] __attribute__((uninitialized));
+ CHECK_LT(entry->msg_len(), LOGGER_ENTRY_MAX_PAYLOAD + 1);
+ memcpy(entry_copy, entry, sizeof(*entry) + entry->msg_len());
lock.unlock();
- // We never prune logs equal to or newer than any LogReaderThreads' `start` value, so the
- // `entry` pointer is safe here without the lock
- if (!entry->Flush(writer, log_id)) {
+
+ if (!reinterpret_cast<SerializedLogEntry*>(entry_copy)->Flush(writer, log_id)) {
return false;
}
+
lock.lock();
}
@@ -266,38 +254,11 @@
}
bool SerializedLogBuffer::Clear(log_id_t id, uid_t uid) {
- // Try three times to clear, then disconnect the readers and try one final time.
- for (int retry = 0; retry < 3; ++retry) {
- {
- auto lock = std::lock_guard{lock_};
- bool prune_success = Prune(id, ULONG_MAX, uid);
- if (prune_success) {
- return true;
- }
- }
- sleep(1);
- }
- // Check if it is still busy after the sleep, we try to prune one entry, not another clear run,
- // so we are looking for the quick side effect of the return value to tell us if we have a
- // _blocked_ reader.
- bool busy = false;
- {
- auto lock = std::lock_guard{lock_};
- busy = !Prune(id, 1, uid);
- }
- // It is still busy, disconnect all readers.
- if (busy) {
- auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};
- for (const auto& reader_thread : reader_list_->reader_threads()) {
- if (reader_thread->IsWatching(id)) {
- LOG(WARNING) << "Kicking blocked reader, " << reader_thread->name()
- << ", from LogBuffer::clear()";
- reader_thread->release_Locked();
- }
- }
- }
auto lock = std::lock_guard{lock_};
- return Prune(id, ULONG_MAX, uid);
+ Prune(id, ULONG_MAX, uid);
+
+ // Clearing SerializedLogBuffer never waits for readers and therefore is always successful.
+ return true;
}
size_t SerializedLogBuffer::GetSizeUsed(log_id_t id) {
diff --git a/logd/SerializedLogBuffer.h b/logd/SerializedLogBuffer.h
index 32fbe5e..294cfe6 100644
--- a/logd/SerializedLogBuffer.h
+++ b/logd/SerializedLogBuffer.h
@@ -55,9 +55,7 @@
private:
bool ShouldLog(log_id_t log_id, const char* msg, uint16_t len);
void MaybePrune(log_id_t log_id) REQUIRES(lock_);
- bool Prune(log_id_t log_id, size_t bytes_to_free, uid_t uid) REQUIRES(lock_);
- void KickReader(LogReaderThread* reader, log_id_t id, size_t bytes_to_free)
- REQUIRES_SHARED(lock_);
+ void Prune(log_id_t log_id, size_t bytes_to_free, uid_t uid) REQUIRES(lock_);
void NotifyReadersOfPrune(log_id_t log_id, const std::list<SerializedLogChunk>::iterator& chunk)
REQUIRES(reader_list_->reader_threads_lock());
void RemoveChunkFromStats(log_id_t log_id, SerializedLogChunk& chunk);
diff --git a/logd/logd_test.cpp b/logd/logd_test.cpp
index 5a0585a..202ab06 100644
--- a/logd/logd_test.cpp
+++ b/logd/logd_test.cpp
@@ -30,6 +30,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
#include <gtest/gtest.h>
#include <log/log_read.h>
@@ -41,6 +42,8 @@
#include "LogReader.h" // pickup LOGD_SNDTIMEO
+using android::base::unique_fd;
+
#ifdef __ANDROID__
static void send_to_control(char* buf, size_t len) {
int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
@@ -836,3 +839,34 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+
+TEST(logd, no_epipe) {
+#ifdef __ANDROID__
+ // Actually generating SIGPIPE in logd is racy, since we need to close the socket quicker than
+ // logd finishes writing the data to it, so we try 10 times, which should be enough to trigger
+ // SIGPIPE if logd isn't ignoring SIGPIPE
+ for (int i = 0; i < 10; ++i) {
+ unique_fd sock1(
+ socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
+ ASSERT_GT(sock1, 0);
+ unique_fd sock2(
+ socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
+ ASSERT_GT(sock2, 0);
+
+ std::string message = "getStatistics 0 1 2 3 4 5 6 7";
+
+ ASSERT_GT(write(sock1, message.c_str(), message.length()), 0);
+ sock1.reset();
+ ASSERT_GT(write(sock2, message.c_str(), message.length()), 0);
+
+ struct pollfd p = {.fd = sock2, .events = POLLIN, .revents = 0};
+
+ int ret = poll(&p, 1, 20);
+ EXPECT_EQ(ret, 1);
+ EXPECT_TRUE(p.revents & POLLIN);
+ EXPECT_FALSE(p.revents & POLL_ERR);
+ }
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}