Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68630a0d authored by Tom Cherry's avatar Tom Cherry
Browse files

logd: refactor LastLogTimes a bit

There's still plenty of work that can be done here, particularly
re-doing the locking so each LogReaderThread does not mutually exclude
the others, but that's out of the scope here.

This change primarily removes the public 'mTimes' from LogBuffer and
creates a new LogReaderList class instead.  It would have merged this
into LogReader, but that creates a circular dependency.

This change also removes the need to reference LogReader or
LogReaderList from LogAudit, LogKLog, and LogListener, instead relying
on LogBuffer()::log() to call LogReaderList::NotifyNewLog().

Test: logging unit tests
Change-Id: Ia874b57a9ec1254af1295bfa6f7af2f92a75755b
parent a269c7c3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ cc_library_static {
        "CommandListener.cpp",
        "LogListener.cpp",
        "LogReader.cpp",
        "LogReaderList.cpp",
        "LogReaderThread.cpp",
        "LogBuffer.cpp",
        "LogBufferElement.cpp",
+1 −4
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
#include <private/android_logger.h>

#include "LogKlog.h"
#include "LogReader.h"
#include "LogUtils.h"
#include "libaudit.h"

@@ -45,10 +44,9 @@
    '<', '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
        '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, '>'

LogAudit::LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg, LogStatistics* stats)
LogAudit::LogAudit(LogBuffer* buf, int fdDmesg, LogStatistics* stats)
    : SocketListener(getLogSocket(), false),
      logbuf(buf),
      reader(reader),
      fdDmesg(fdDmesg),
      main(__android_logger_property_get_bool("ro.logd.auditd.main", BOOL_DEFAULT_TRUE)),
      events(__android_logger_property_get_bool("ro.logd.auditd.events", BOOL_DEFAULT_TRUE)),
@@ -344,7 +342,6 @@ int LogAudit::logPrint(const char* fmt, ...) {
    free(str);

    if (notify) {
        reader->notifyNewLog(notify);
        if (rc < 0) {
            rc = message_len;
        }
+1 −4
Original line number Diff line number Diff line
@@ -23,18 +23,15 @@
#include "LogBuffer.h"
#include "LogStatistics.h"

class LogReader;

class LogAudit : public SocketListener {
    LogBuffer* logbuf;
    LogReader* reader;
    int fdDmesg;  // fdDmesg >= 0 is functionally bool dmesg
    bool main;
    bool events;
    bool initialized;

  public:
    LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg, LogStatistics* stats);
    LogAudit(LogBuffer* buf, int fdDmesg, LogStatistics* stats);
    int log(char* buf, size_t len);

  protected:
+29 −42
Original line number Diff line number Diff line
@@ -51,20 +51,15 @@ void LogBuffer::init() {
        }
    }
    // Release any sleeping reader threads to dump their current content.
    LogReaderThread::wrlock();

    LastLogTimes::iterator times = mTimes.begin();
    while (times != mTimes.end()) {
        LogReaderThread* entry = times->get();
        entry->triggerReader_Locked();
        times++;
    auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};
    for (const auto& reader_thread : reader_list_->reader_threads()) {
        reader_thread->triggerReader_Locked();
    }

    LogReaderThread::unlock();
}

LogBuffer::LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune, LogStatistics* stats)
    : mTimes(*times), tags_(tags), prune_(prune), stats_(stats) {
LogBuffer::LogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune,
                     LogStatistics* stats)
    : reader_list_(reader_list), tags_(tags), prune_(prune), stats_(stats) {
    pthread_rwlock_init(&mLogElementsLock, nullptr);

    log_id_for_each(i) {
@@ -355,6 +350,7 @@ void LogBuffer::log(LogBufferElement* elem) {
    mLogElements.push_back(elem);
    stats_->Add(elem);
    maybePrune(elem->getLogId());
    reader_list_->NotifyNewLog(1 << elem->getLogId());
}

// LogBuffer::wrlock() must be held when this function is called.
@@ -523,9 +519,8 @@ void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows
        android::prdebug("Kicking blocked reader, pid %d, from LogBuffer::kickMe()\n",
                         me->client()->getPid());
        me->release_Locked();
    } else if (me->timeout().tv_sec || me->timeout().tv_nsec) {
        // Allow a blocked WRAP timeout reader to
        // trigger and start reporting the log data.
    } else if (me->deadline().time_since_epoch().count() != 0) {
        // Allow a blocked WRAP deadline reader to trigger and start reporting the log data.
        me->triggerReader_Locked();
    } else {
        // tell slow reader to skip entries to catch up
@@ -588,18 +583,18 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
    bool busy = false;
    bool clearAll = pruneRows == ULONG_MAX;

    LogReaderThread::rdlock();
    auto reader_threads_lock = std::lock_guard{reader_list_->reader_threads_lock()};

    // Region locked?
    LastLogTimes::iterator times = mTimes.begin();
    while (times != mTimes.end()) {
        LogReaderThread* entry = times->get();
        if (entry->IsWatching(id) && (!oldest || oldest->start() > entry->start() ||
                                      (oldest->start() == entry->start() &&
                                       (entry->timeout().tv_sec || entry->timeout().tv_nsec)))) {
            oldest = entry;
    for (const auto& reader_thread : reader_list_->reader_threads()) {
        if (!reader_thread->IsWatching(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();
        }
        times++;
    }

    LogBufferElementCollection::iterator it;
@@ -628,7 +623,6 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
                break;
            }
        }
        LogReaderThread::unlock();
        return busy;
    }

@@ -884,8 +878,6 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
        }
    }

    LogReaderThread::unlock();

    return (pruneRows > 0) && busy;
}

@@ -907,20 +899,15 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
            // readers and let the clear run (below) deal with determining
            // if we are still blocked and return an error code to caller.
            if (busy) {
                LogReaderThread::wrlock();
                LastLogTimes::iterator times = mTimes.begin();
                while (times != mTimes.end()) {
                    LogReaderThread* entry = times->get();
                    // Killer punch
                    if (entry->IsWatching(id)) {
                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)) {
                        android::prdebug(
                                "Kicking blocked reader, pid %d, from LogBuffer::clear()\n",
                                entry->client()->getPid());
                        entry->release_Locked();
                                reader_thread->client()->getPid());
                        reader_thread->release_Locked();
                    }
                    times++;
                }
                LogReaderThread::unlock();
            }
        }
        wrlock();
@@ -954,9 +941,9 @@ unsigned long LogBuffer::getSize(log_id_t id) {
    return retval;
}

uint64_t LogBuffer::flushTo(SocketClient* reader, uint64_t start, pid_t* lastTid, bool privileged,
                            bool security,
                            const std::function<int(const LogBufferElement* element)>& filter) {
uint64_t LogBuffer::flushTo(
        SocketClient* reader, uint64_t start, pid_t* lastTid, bool privileged, bool security,
        const std::function<FlushToResult(const LogBufferElement* element)>& filter) {
    LogBufferElementCollection::iterator it;
    uid_t uid = reader->getUid();

@@ -994,11 +981,11 @@ uint64_t LogBuffer::flushTo(SocketClient* reader, uint64_t start, pid_t* lastTid

        // NB: calling out to another object with wrlock() held (safe)
        if (filter) {
            int ret = filter(element);
            if (ret == false) {
            FlushToResult ret = filter(element);
            if (ret == FlushToResult::kSkip) {
                continue;
            }
            if (ret != true) {
            if (ret == FlushToResult::kStop) {
                break;
            }
        }
+13 −6
Original line number Diff line number Diff line
@@ -27,13 +27,21 @@
#include <sysutils/SocketClient.h>

#include "LogBufferElement.h"
#include "LogReaderThread.h"
#include "LogStatistics.h"
#include "LogTags.h"
#include "LogWhiteBlackList.h"

typedef std::list<LogBufferElement*> LogBufferElementCollection;

class LogReaderList;
class LogReaderThread;

enum class FlushToResult {
    kSkip,
    kStop,
    kWrite,
};

class LogBuffer {
    LogBufferElementCollection mLogElements;
    pthread_rwlock_t mLogElementsLock;
@@ -54,9 +62,7 @@ class LogBuffer {
    void log(LogBufferElement* elem);

  public:
    LastLogTimes& mTimes;

    LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune, LogStatistics* stats);
    LogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune, LogStatistics* stats);
    ~LogBuffer();
    void init();

@@ -68,7 +74,7 @@ class LogBuffer {
    uint64_t flushTo(SocketClient* writer, uint64_t start,
                     pid_t* lastTid,  // &lastTid[LOG_ID_MAX] or nullptr
                     bool privileged, bool security,
                     const std::function<int(const LogBufferElement* element)>& filter);
                     const std::function<FlushToResult(const LogBufferElement* element)>& filter);

    bool clear(log_id_t id, uid_t uid = AID_ROOT);
    unsigned long getSize(log_id_t id);
@@ -96,6 +102,7 @@ class LogBuffer {
    // there are no logs for the given log type. Requires mLogElementsLock to be held.
    LogBufferElementCollection::iterator GetOldest(log_id_t log_id);

    LogReaderList* reader_list_;
    LogTags* tags_;
    PruneList* prune_;
    LogStatistics* stats_;
Loading