Revert "logd: drop mSequence from LogBufferElement"
This reverts commit 5a34d6ea43d28f3b5d27bf6dd5b9fa31ec033531.
There is a long standing bug that logd will leak memory during its
prune process if the time on the device changes significantly forwards
then backwards. This is due to using the timestamp of each log
message to determine what log messages are yet to be processed by a
reader thread.
Various attempts have been made to rectify this, but the only solution
that safely fixes this issue is to go back to using sequence numbers
on the log messages.
Bug: 64675203
Bug: 77971811
Bug: 149340579
Bug: 150923384
Test: logcat output looks sane
Change-Id: Ibce79cf184eb29a4914f3e42a8cb2868d04dc165
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index f21b94c..5bec076 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <unordered_map>
+#include <utility>
#include <cutils/properties.h>
#include <private/android_logger.h>
@@ -560,12 +561,11 @@
}
void clear(LogBufferElement* element) {
- log_time current =
- element->getRealTime() - log_time(EXPIRE_RATELIMIT, 0);
+ uint64_t current = element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
LogBufferElement* mapElement = it->second;
- if ((mapElement->getDropped() >= EXPIRE_THRESHOLD) &&
- (current > mapElement->getRealTime())) {
+ if (mapElement->getDropped() >= EXPIRE_THRESHOLD &&
+ current > mapElement->getRealTime().nsec()) {
it = map.erase(it);
} else {
++it;
@@ -683,7 +683,7 @@
mLastSet[id] = true;
}
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && oldest->mStart <= element->getSequence()) {
busy = true;
kickMe(oldest, id, pruneRows);
break;
@@ -771,7 +771,7 @@
while (it != mLogElements.end()) {
LogBufferElement* element = *it;
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && oldest->mStart <= element->getSequence()) {
busy = true;
// Do not let chatty eliding trigger any reader mitigation
break;
@@ -923,7 +923,7 @@
mLastSet[id] = true;
}
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && oldest->mStart <= element->getSequence()) {
busy = true;
if (!whitelist) kickMe(oldest, id, pruneRows);
break;
@@ -956,7 +956,7 @@
mLastSet[id] = true;
}
- if (oldest && (oldest->mStart <= element->getRealTime().nsec())) {
+ if (oldest && oldest->mStart <= element->getSequence()) {
busy = true;
kickMe(oldest, id, pruneRows);
break;
@@ -1045,42 +1045,32 @@
return retval;
}
-log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
- pid_t* lastTid, bool privileged, bool security,
- int (*filter)(const LogBufferElement* element,
- void* arg),
- void* arg) {
+uint64_t LogBuffer::flushTo(SocketClient* reader, uint64_t start, pid_t* lastTid, bool privileged,
+ bool security,
+ int (*filter)(const LogBufferElement* element, void* arg), void* arg) {
LogBufferElementCollection::iterator it;
uid_t uid = reader->getUid();
rdlock();
- if (start == log_time::EPOCH) {
+ if (start <= 1) {
// client wants to start from the beginning
it = mLogElements.begin();
} else {
- // Cap to 300 iterations we look back for out-of-order entries.
- size_t count = 300;
// Client wants to start from some specified time. Chances are
// we are better off starting from the end of the time sorted list.
- LogBufferElementCollection::iterator last;
- for (last = it = mLogElements.end(); it != mLogElements.begin();
+ for (it = mLogElements.end(); it != mLogElements.begin();
/* do nothing */) {
--it;
LogBufferElement* element = *it;
- if (element->getRealTime() > start) {
- last = it;
- } else if (element->getRealTime() == start) {
- last = ++it;
- break;
- } else if (!--count) {
+ if (element->getSequence() <= start) {
+ it++;
break;
}
}
- it = last;
}
- log_time curr = start;
+ uint64_t curr = start;
LogBufferElement* lastElement = nullptr; // iterator corruption paranoia
static const size_t maxSkip = 4194304; // maximum entries to skip