Merge changes I6555c135,If5723ff4 am: d9982803ed

am: b3259f39c2

Change-Id: I9823a3b1e791d07dadb3fafb6b6e0b5c8978034e
This commit is contained in:
Mark Salyzyn 2017-04-20 17:54:29 +00:00 committed by android-build-merger
commit 529be90503
11 changed files with 68 additions and 56 deletions

View file

@ -1216,7 +1216,12 @@ TEST(logcat, blocking_clear) {
signal(SIGALRM, caught_blocking_clear); signal(SIGALRM, caught_blocking_clear);
alarm(2); alarm(2);
while (fgets(buffer, sizeof(buffer), fp)) { while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncmp(buffer, "clearLog: ", 10)) { if (!strncmp(buffer, "clearLog: ", strlen("clearLog: "))) {
fprintf(stderr, "WARNING: Test lacks permission to run :-(\n");
count = signals = 1;
break;
}
if (!strncmp(buffer, "failed to clear", strlen("failed to clear"))) {
fprintf(stderr, "WARNING: Test lacks permission to run :-(\n"); fprintf(stderr, "WARNING: Test lacks permission to run :-(\n");
count = signals = 1; count = signals = 1;
break; break;

View file

@ -44,14 +44,14 @@ FlushCommand::FlushCommand(LogReader& reader, bool nonBlock, unsigned long tail,
// LogTimeEntrys, and spawn a transitory per-client thread to // LogTimeEntrys, and spawn a transitory per-client thread to
// work at filing data to the socket. // work at filing data to the socket.
// //
// global LogTimeEntry::lock() is used to protect access, // global LogTimeEntry::wrlock() is used to protect access,
// reference counts are used to ensure that individual // reference counts are used to ensure that individual
// LogTimeEntry lifetime is managed when not protected. // LogTimeEntry lifetime is managed when not protected.
void FlushCommand::runSocketCommand(SocketClient* client) { void FlushCommand::runSocketCommand(SocketClient* client) {
LogTimeEntry* entry = NULL; LogTimeEntry* entry = NULL;
LastLogTimes& times = mReader.logbuf().mTimes; LastLogTimes& times = mReader.logbuf().mTimes;
LogTimeEntry::lock(); LogTimeEntry::wrlock();
LastLogTimes::iterator it = times.begin(); LastLogTimes::iterator it = times.begin();
while (it != times.end()) { while (it != times.end()) {
entry = (*it); entry = (*it);

View file

@ -277,7 +277,7 @@ int LogAudit::logPrint(const char* fmt, ...) {
++cp; ++cp;
} }
tid = pid; tid = pid;
logbuf->lock(); logbuf->wrlock();
uid = logbuf->pidToUid(pid); uid = logbuf->pidToUid(pid);
logbuf->unlock(); logbuf->unlock();
memmove(pidptr, cp, strlen(cp) + 1); memmove(pidptr, cp, strlen(cp) + 1);
@ -322,7 +322,7 @@ int LogAudit::logPrint(const char* fmt, ...) {
pid = tid; pid = tid;
comm = "auditd"; comm = "auditd";
} else { } else {
logbuf->lock(); logbuf->wrlock();
comm = commfree = logbuf->pidToName(pid); comm = commfree = logbuf->pidToName(pid);
logbuf->unlock(); logbuf->unlock();
if (!comm) { if (!comm) {

View file

@ -72,7 +72,7 @@ void LogBuffer::init() {
// as the act of mounting /data would trigger persist.logd.timestamp to // as the act of mounting /data would trigger persist.logd.timestamp to
// be corrected. 1/30 corner case YMMV. // be corrected. 1/30 corner case YMMV.
// //
pthread_mutex_lock(&mLogElementsLock); rdlock();
LogBufferElementCollection::iterator it = mLogElements.begin(); LogBufferElementCollection::iterator it = mLogElements.begin();
while ((it != mLogElements.end())) { while ((it != mLogElements.end())) {
LogBufferElement* e = *it; LogBufferElement* e = *it;
@ -87,7 +87,7 @@ void LogBuffer::init() {
} }
++it; ++it;
} }
pthread_mutex_unlock(&mLogElementsLock); unlock();
} }
// We may have been triggered by a SIGHUP. Release any sleeping reader // We may have been triggered by a SIGHUP. Release any sleeping reader
@ -95,7 +95,7 @@ void LogBuffer::init() {
// //
// NB: this is _not_ performed in the context of a SIGHUP, it is // NB: this is _not_ performed in the context of a SIGHUP, it is
// performed during startup, and in context of reinit administrative thread // performed during startup, and in context of reinit administrative thread
LogTimeEntry::lock(); LogTimeEntry::wrlock();
LastLogTimes::iterator times = mTimes.begin(); LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) { while (times != mTimes.end()) {
@ -111,7 +111,7 @@ void LogBuffer::init() {
LogBuffer::LogBuffer(LastLogTimes* times) LogBuffer::LogBuffer(LastLogTimes* times)
: monotonic(android_log_clockid() == CLOCK_MONOTONIC), mTimes(*times) { : monotonic(android_log_clockid() == CLOCK_MONOTONIC), mTimes(*times) {
pthread_mutex_init(&mLogElementsLock, nullptr); pthread_rwlock_init(&mLogElementsLock, nullptr);
log_id_for_each(i) { log_id_for_each(i) {
lastLoggedElements[i] = nullptr; lastLoggedElements[i] = nullptr;
@ -207,15 +207,15 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
} }
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
// Log traffic received to total // Log traffic received to total
pthread_mutex_lock(&mLogElementsLock); wrlock();
stats.addTotal(elem); stats.addTotal(elem);
pthread_mutex_unlock(&mLogElementsLock); unlock();
delete elem; delete elem;
return -EACCES; return -EACCES;
} }
} }
pthread_mutex_lock(&mLogElementsLock); wrlock();
LogBufferElement* currentLast = lastLoggedElements[log_id]; LogBufferElement* currentLast = lastLoggedElements[log_id];
if (currentLast) { if (currentLast) {
LogBufferElement* dropped = droppedElements[log_id]; LogBufferElement* dropped = droppedElements[log_id];
@ -316,14 +316,14 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
// check for overflow // check for overflow
if (total >= UINT32_MAX) { if (total >= UINT32_MAX) {
log(currentLast); log(currentLast);
pthread_mutex_unlock(&mLogElementsLock); unlock();
return len; return len;
} }
stats.addTotal(currentLast); stats.addTotal(currentLast);
delete currentLast; delete currentLast;
swab = total; swab = total;
event->payload.data = htole32(swab); event->payload.data = htole32(swab);
pthread_mutex_unlock(&mLogElementsLock); unlock();
return len; return len;
} }
if (count == USHRT_MAX) { if (count == USHRT_MAX) {
@ -340,7 +340,7 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
} }
droppedElements[log_id] = currentLast; droppedElements[log_id] = currentLast;
lastLoggedElements[log_id] = elem; lastLoggedElements[log_id] = elem;
pthread_mutex_unlock(&mLogElementsLock); unlock();
return len; return len;
} }
if (dropped) { // State 1 or 2 if (dropped) { // State 1 or 2
@ -358,12 +358,12 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
lastLoggedElements[log_id] = new LogBufferElement(*elem); lastLoggedElements[log_id] = new LogBufferElement(*elem);
log(elem); log(elem);
pthread_mutex_unlock(&mLogElementsLock); unlock();
return len; return len;
} }
// assumes mLogElementsLock held, owns elem, will look after garbage collection // assumes LogBuffer::wrlock() held, owns elem, look after garbage collection
void LogBuffer::log(LogBufferElement* elem) { void LogBuffer::log(LogBufferElement* elem) {
// cap on how far back we will sort in-place, otherwise append // cap on how far back we will sort in-place, otherwise append
static uint32_t too_far_back = 5; // five seconds static uint32_t too_far_back = 5; // five seconds
@ -384,7 +384,7 @@ void LogBuffer::log(LogBufferElement* elem) {
bool end_set = false; bool end_set = false;
bool end_always = false; bool end_always = false;
LogTimeEntry::lock(); LogTimeEntry::rdlock();
LastLogTimes::iterator times = mTimes.begin(); LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) { while (times != mTimes.end()) {
@ -426,7 +426,7 @@ void LogBuffer::log(LogBufferElement* elem) {
// Prune at most 10% of the log entries or maxPrune, whichever is less. // Prune at most 10% of the log entries or maxPrune, whichever is less.
// //
// mLogElementsLock must be held when this function is called. // LogBuffer::wrlock() must be held when this function is called.
void LogBuffer::maybePrune(log_id_t id) { void LogBuffer::maybePrune(log_id_t id) {
size_t sizes = stats.sizes(id); size_t sizes = stats.sizes(id);
unsigned long maxSize = log_buffer_size(id); unsigned long maxSize = log_buffer_size(id);
@ -650,14 +650,14 @@ class LogBufferElementLast {
// The third thread is optional, and only gets hit if there was a whitelist // The third thread is optional, and only gets hit if there was a whitelist
// and more needs to be pruned against the backstop of the region lock. // and more needs to be pruned against the backstop of the region lock.
// //
// mLogElementsLock must be held when this function is called. // LogBuffer::wrlock() must be held when this function is called.
// //
bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
LogTimeEntry* oldest = nullptr; LogTimeEntry* oldest = nullptr;
bool busy = false; bool busy = false;
bool clearAll = pruneRows == ULONG_MAX; bool clearAll = pruneRows == ULONG_MAX;
LogTimeEntry::lock(); LogTimeEntry::rdlock();
// Region locked? // Region locked?
LastLogTimes::iterator times = mTimes.begin(); LastLogTimes::iterator times = mTimes.begin();
@ -1017,15 +1017,15 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
// one entry, not another clear run, so we are looking for // one entry, not another clear run, so we are looking for
// the quick side effect of the return value to tell us if // the quick side effect of the return value to tell us if
// we have a _blocked_ reader. // we have a _blocked_ reader.
pthread_mutex_lock(&mLogElementsLock); wrlock();
busy = prune(id, 1, uid); busy = prune(id, 1, uid);
pthread_mutex_unlock(&mLogElementsLock); unlock();
// It is still busy, blocked reader(s), lets kill them all! // It is still busy, blocked reader(s), lets kill them all!
// otherwise, lets be a good citizen and preserve the slow // otherwise, lets be a good citizen and preserve the slow
// readers and let the clear run (below) deal with determining // readers and let the clear run (below) deal with determining
// if we are still blocked and return an error code to caller. // if we are still blocked and return an error code to caller.
if (busy) { if (busy) {
LogTimeEntry::lock(); LogTimeEntry::wrlock();
LastLogTimes::iterator times = mTimes.begin(); LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) { while (times != mTimes.end()) {
LogTimeEntry* entry = (*times); LogTimeEntry* entry = (*times);
@ -1038,9 +1038,9 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
LogTimeEntry::unlock(); LogTimeEntry::unlock();
} }
} }
pthread_mutex_lock(&mLogElementsLock); wrlock();
busy = prune(id, ULONG_MAX, uid); busy = prune(id, ULONG_MAX, uid);
pthread_mutex_unlock(&mLogElementsLock); unlock();
if (!busy || !--retry) { if (!busy || !--retry) {
break; break;
} }
@ -1051,9 +1051,9 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
// get the used space associated with "id". // get the used space associated with "id".
unsigned long LogBuffer::getSizeUsed(log_id_t id) { unsigned long LogBuffer::getSizeUsed(log_id_t id) {
pthread_mutex_lock(&mLogElementsLock); rdlock();
size_t retval = stats.sizes(id); size_t retval = stats.sizes(id);
pthread_mutex_unlock(&mLogElementsLock); unlock();
return retval; return retval;
} }
@ -1063,17 +1063,17 @@ int LogBuffer::setSize(log_id_t id, unsigned long size) {
if (!__android_logger_valid_buffer_size(size)) { if (!__android_logger_valid_buffer_size(size)) {
return -1; return -1;
} }
pthread_mutex_lock(&mLogElementsLock); wrlock();
log_buffer_size(id) = size; log_buffer_size(id) = size;
pthread_mutex_unlock(&mLogElementsLock); unlock();
return 0; return 0;
} }
// get the total space allocated to "id" // get the total space allocated to "id"
unsigned long LogBuffer::getSize(log_id_t id) { unsigned long LogBuffer::getSize(log_id_t id) {
pthread_mutex_lock(&mLogElementsLock); rdlock();
size_t retval = log_buffer_size(id); size_t retval = log_buffer_size(id);
pthread_mutex_unlock(&mLogElementsLock); unlock();
return retval; return retval;
} }
@ -1085,7 +1085,7 @@ log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
LogBufferElementCollection::iterator it; LogBufferElementCollection::iterator it;
uid_t uid = reader->getUid(); uid_t uid = reader->getUid();
pthread_mutex_lock(&mLogElementsLock); rdlock();
if (start == log_time::EPOCH) { if (start == log_time::EPOCH) {
// client wants to start from the beginning // client wants to start from the beginning
@ -1143,7 +1143,7 @@ log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
continue; continue;
} }
// NB: calling out to another object with mLogElementsLock held (safe) // NB: calling out to another object with wrlock() held (safe)
if (filter) { if (filter) {
int ret = (*filter)(element, arg); int ret = (*filter)(element, arg);
if (ret == false) { if (ret == false) {
@ -1166,7 +1166,7 @@ log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
(element->getDropped() && !sameTid) ? 0 : element->getTid(); (element->getDropped() && !sameTid) ? 0 : element->getTid();
} }
pthread_mutex_unlock(&mLogElementsLock); unlock();
// range locking in LastLogTimes looks after us // range locking in LastLogTimes looks after us
max = element->flushTo(reader, this, privileged, sameTid); max = element->flushTo(reader, this, privileged, sameTid);
@ -1176,20 +1176,20 @@ log_time LogBuffer::flushTo(SocketClient* reader, const log_time& start,
} }
skip = maxSkip; skip = maxSkip;
pthread_mutex_lock(&mLogElementsLock); rdlock();
} }
pthread_mutex_unlock(&mLogElementsLock); unlock();
return max; return max;
} }
std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid, std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid,
unsigned int logMask) { unsigned int logMask) {
pthread_mutex_lock(&mLogElementsLock); wrlock();
std::string ret = stats.format(uid, pid, logMask); std::string ret = stats.format(uid, pid, logMask);
pthread_mutex_unlock(&mLogElementsLock); unlock();
return ret; return ret;
} }

View file

@ -76,7 +76,7 @@ typedef std::list<LogBufferElement*> LogBufferElementCollection;
class LogBuffer { class LogBuffer {
LogBufferElementCollection mLogElements; LogBufferElementCollection mLogElements;
pthread_mutex_t mLogElementsLock; pthread_rwlock_t mLogElementsLock;
LogStatistics stats; LogStatistics stats;
@ -154,7 +154,7 @@ class LogBuffer {
return tags.tagToName(tag); return tags.tagToName(tag);
} }
// helper must be protected directly or implicitly by lock()/unlock() // helper must be protected directly or implicitly by wrlock()/unlock()
const char* pidToName(pid_t pid) { const char* pidToName(pid_t pid) {
return stats.pidToName(pid); return stats.pidToName(pid);
} }
@ -164,11 +164,14 @@ class LogBuffer {
const char* uidToName(uid_t uid) { const char* uidToName(uid_t uid) {
return stats.uidToName(uid); return stats.uidToName(uid);
} }
void lock() { void wrlock() {
pthread_mutex_lock(&mLogElementsLock); pthread_rwlock_wrlock(&mLogElementsLock);
}
void rdlock() {
pthread_rwlock_rdlock(&mLogElementsLock);
} }
void unlock() { void unlock() {
pthread_mutex_unlock(&mLogElementsLock); pthread_rwlock_unlock(&mLogElementsLock);
} }
private: private:

View file

@ -121,7 +121,7 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogBuffer* parent
} }
static const char format_uid[] = "uid=%u%s%s %s %u line%s"; static const char format_uid[] = "uid=%u%s%s %s %u line%s";
parent->lock(); parent->wrlock();
const char* name = parent->uidToName(mUid); const char* name = parent->uidToName(mUid);
parent->unlock(); parent->unlock();
const char* commName = android::tidToName(mTid); const char* commName = android::tidToName(mTid);
@ -129,7 +129,7 @@ size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogBuffer* parent
commName = android::tidToName(mPid); commName = android::tidToName(mPid);
} }
if (!commName) { if (!commName) {
parent->lock(); parent->wrlock();
commName = parent->pidToName(mPid); commName = parent->pidToName(mPid);
parent->unlock(); parent->unlock();
} }

View file

@ -579,7 +579,7 @@ int LogKlog::log(const char* buf, ssize_t len) {
const pid_t tid = pid; const pid_t tid = pid;
uid_t uid = AID_ROOT; uid_t uid = AID_ROOT;
if (pid) { if (pid) {
logbuf->lock(); logbuf->wrlock();
uid = logbuf->pidToUid(pid); uid = logbuf->pidToUid(pid);
logbuf->unlock(); logbuf->unlock();
} }

View file

@ -111,7 +111,7 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) { if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
// Allow writer to get some cycles, and wait for pending notifications // Allow writer to get some cycles, and wait for pending notifications
sched_yield(); sched_yield();
LogTimeEntry::lock(); LogTimeEntry::wrlock();
LogTimeEntry::unlock(); LogTimeEntry::unlock();
sched_yield(); sched_yield();
nonBlock = true; nonBlock = true;
@ -212,7 +212,7 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
void LogReader::doSocketDelete(SocketClient* cli) { void LogReader::doSocketDelete(SocketClient* cli) {
LastLogTimes& times = mLogbuf.mTimes; LastLogTimes& times = mLogbuf.mTimes;
LogTimeEntry::lock(); LogTimeEntry::wrlock();
LastLogTimes::iterator it = times.begin(); LastLogTimes::iterator it = times.begin();
while (it != times.end()) { while (it != times.end()) {
LogTimeEntry* entry = (*it); LogTimeEntry* entry = (*it);

View file

@ -228,6 +228,7 @@ void LogStatistics::drop(LogBufferElement* element) {
} }
// caller must own and free character string // caller must own and free character string
// Requires parent LogBuffer::wrlock() to be held
const char* LogStatistics::uidToName(uid_t uid) const { const char* LogStatistics::uidToName(uid_t uid) const {
// Local hard coded favourites // Local hard coded favourites
if (uid == AID_LOGD) { if (uid == AID_LOGD) {

View file

@ -78,7 +78,7 @@ void LogTimeEntry::startReader_Locked(void) {
void LogTimeEntry::threadStop(void* obj) { void LogTimeEntry::threadStop(void* obj) {
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj); LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
lock(); wrlock();
if (me->mNonBlock) { if (me->mNonBlock) {
me->error_Locked(); me->error_Locked();
@ -134,7 +134,7 @@ void* LogTimeEntry::threadStart(void* obj) {
me->leadingDropped = true; me->leadingDropped = true;
lock(); wrlock();
log_time start = me->mStart; log_time start = me->mStart;
@ -160,7 +160,7 @@ void* LogTimeEntry::threadStart(void* obj) {
start = logbuf.flushTo(client, start, me->mLastTid, privileged, start = logbuf.flushTo(client, start, me->mLastTid, privileged,
security, FilterSecondPass, me); security, FilterSecondPass, me);
lock(); wrlock();
if (start == LogBufferElement::FLUSH_ERROR) { if (start == LogBufferElement::FLUSH_ERROR) {
me->error_Locked(); me->error_Locked();
@ -191,7 +191,7 @@ void* LogTimeEntry::threadStart(void* obj) {
int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) { int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj); LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
LogTimeEntry::lock(); LogTimeEntry::wrlock();
if (me->leadingDropped) { if (me->leadingDropped) {
if (element->getDropped()) { if (element->getDropped()) {
@ -219,7 +219,7 @@ int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) { int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj); LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
LogTimeEntry::lock(); LogTimeEntry::wrlock();
me->mStart = element->getRealTime(); me->mStart = element->getRealTime();

View file

@ -61,7 +61,10 @@ class LogTimeEntry {
const log_time mEnd; // only relevant if mNonBlock const log_time mEnd; // only relevant if mNonBlock
// Protect List manipulations // Protect List manipulations
static void lock(void) { static void wrlock(void) {
pthread_mutex_lock(&timesLock);
}
static void rdlock(void) {
pthread_mutex_lock(&timesLock); pthread_mutex_lock(&timesLock);
} }
static void unlock(void) { static void unlock(void) {
@ -104,7 +107,7 @@ class LogTimeEntry {
mError = true; mError = true;
} }
void error(void) { void error(void) {
lock(); wrlock();
error_Locked(); error_Locked();
unlock(); unlock();
} }