diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp index 138ab2814..fbe6ea099 100644 --- a/logd/LogListener.cpp +++ b/logd/LogListener.cpp @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include @@ -31,33 +33,47 @@ #include "LogUtils.h" LogListener::LogListener(LogBuffer* buf, LogReader* reader) - : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {} + : socket_(GetLogSocket()), logbuf_(buf), reader_(reader) {} -bool LogListener::onDataAvailable(SocketClient* cli) { +bool LogListener::StartListener() { + if (socket_ <= 0) { + return false; + } + auto thread = std::thread(&LogListener::ThreadFunction, this); + thread.detach(); + return true; +} + +void LogListener::ThreadFunction() { static bool name_set; if (!name_set) { prctl(PR_SET_NAME, "logd.writer"); name_set = true; } + while (true) { + HandleData(); + } +} + +void LogListener::HandleData() { // + 1 to ensure null terminator if MAX_PAYLOAD buffer is received - char buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1]; - struct iovec iov = { buffer, sizeof(buffer) - 1 }; + __attribute__((uninitialized)) char + buffer[sizeof(android_log_header_t) + LOGGER_ENTRY_MAX_PAYLOAD + 1]; + struct iovec iov = {buffer, sizeof(buffer) - 1}; alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr hdr = { nullptr, 0, &iov, 1, control, sizeof(control), 0, }; - int socket = cli->getSocket(); - // To clear the entire buffer is secure/safe, but this contributes to 1.68% // overhead under logging load. We are safe because we check counts, but // still need to clear null terminator // memset(buffer, 0, sizeof(buffer)); - ssize_t n = recvmsg(socket, &hdr, 0); + ssize_t n = recvmsg(socket_, &hdr, 0); if (n <= (ssize_t)(sizeof(android_log_header_t))) { - return false; + return; } buffer[n] = 0; @@ -75,14 +91,14 @@ bool LogListener::onDataAvailable(SocketClient* cli) { } if (cred == nullptr) { - return false; + return; } if (cred->uid == AID_LOGD) { // ignore log messages we send to ourself. // Such log messages are often generated by libraries we depend on // which use standard Android logging. - return false; + return; } android_log_header_t* header = @@ -90,13 +106,13 @@ bool LogListener::onDataAvailable(SocketClient* cli) { log_id_t logId = static_cast(header->id); if (/* logId < LOG_ID_MIN || */ logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) { - return false; + return; } if ((logId == LOG_ID_SECURITY) && (!__android_log_security() || !clientHasLogCredentials(cred->uid, cred->gid, cred->pid))) { - return false; + return; } char* msg = ((char*)buffer) + sizeof(android_log_header_t); @@ -105,16 +121,16 @@ bool LogListener::onDataAvailable(SocketClient* cli) { // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a // truncated message to the logs. - int res = logbuf->log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg, - ((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX); + int res = logbuf_->log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg, + ((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX); if (res > 0) { - reader->notifyNewLog(static_cast(1 << logId)); + reader_->notifyNewLog(static_cast(1 << logId)); } - return true; + return; } -int LogListener::getLogSocket() { +int LogListener::GetLogSocket() { static const char socketName[] = "logdw"; int sock = android_get_control_socket(socketName); diff --git a/logd/LogListener.h b/logd/LogListener.h index 8fe3da46d..ce3e0f23a 100644 --- a/logd/LogListener.h +++ b/logd/LogListener.h @@ -14,24 +14,22 @@ * limitations under the License. */ -#ifndef _LOGD_LOG_LISTENER_H__ -#define _LOGD_LOG_LISTENER_H__ +#pragma once -#include +#include "LogBuffer.h" #include "LogReader.h" -class LogListener : public SocketListener { - LogBuffer* logbuf; - LogReader* reader; +class LogListener { + public: + LogListener(LogBuffer* buf, LogReader* reader); + bool StartListener(); - public: - LogListener(LogBuffer* buf, LogReader* reader); + private: + void ThreadFunction(); + void HandleData(); + static int GetLogSocket(); - protected: - virtual bool onDataAvailable(SocketClient* cli); - - private: - static int getLogSocket(); + int socket_; + LogBuffer* logbuf_; + LogReader* reader_; }; - -#endif diff --git a/logd/main.cpp b/logd/main.cpp index d9dd249f1..ceddd0f85 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -304,8 +304,7 @@ int main(int argc, char* argv[]) { // and LogReader is notified to send updates to connected clients. LogListener* swl = new LogListener(logBuf, reader); - // Backlog and /proc/sys/net/unix/max_dgram_qlen set to large value - if (swl->startListener(600)) { + if (!swl->StartListener()) { return EXIT_FAILURE; }