diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp index 7df1123d5..3f5fdcef4 100644 --- a/logd/LogBufferElement.cpp +++ b/logd/LogBufferElement.cpp @@ -30,7 +30,7 @@ #include "LogReader.h" const uint64_t LogBufferElement::FLUSH_ERROR(0); -atomic_int_fast64_t LogBufferElement::sequence; +atomic_int_fast64_t LogBufferElement::sequence(1); LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp index 7d1464899..d578c04db 100644 --- a/logd/LogKlog.cpp +++ b/logd/LogKlog.cpp @@ -45,8 +45,8 @@ static char *is_prio(char *s) { } char c; while ((c = *s++)) { - if (!isdigit(c) && (c == '>')) { - return s; + if (!isdigit(c)) { + return (c == '>') ? s : NULL; } } return NULL; @@ -65,17 +65,15 @@ static char *is_timestamp(char *s) { while ((c = *s++)) { if ((c == '.') && first_period) { first_period = false; - continue; - } - if (!isdigit(c) && (c == ']')) { - return s; + } else if (!isdigit(c)) { + return ((c == ']') && !first_period && (*s == ' ')) ? s : NULL; } } return NULL; } // Like strtok_r with "\r\n" except that we look for log signatures (regex) -// \(\(<[0-9]+>\)\([[] *[0-9]+[]]\)\{0,1\}\|[[] *[0-9]+[]]\) +// \(\(<[0-9]+>\)\([[] *[0-9]+[.][0-9]+[]] \)\{0,1\}\|[[] *[0-9]+[.][0-9]+[]] \) // and split if we see a second one without a newline. #define SIGNATURE_MASK 0xF0 @@ -547,10 +545,21 @@ int LogKlog::log(const char *buf) { } } size_t l = etag - tag; + // skip leading space while (isspace(*buf)) { ++buf; } - size_t n = 1 + l + 1 + strlen(buf) + 1; + // truncate trailing space + size_t b = strlen(buf); + while (b && isspace(buf[b-1])) { + --b; + } + // trick ... allow tag with empty content to be logged. log() drops empty + if (!b && l) { + buf = " "; + b = 1; + } + size_t n = 1 + l + 1 + b + 1; // Allocate a buffer to hold the interpreted log message int rc = n; @@ -572,7 +581,8 @@ int LogKlog::log(const char *buf) { ++np; // Copy main message to the remainder - strcpy(np, buf); + strncpy(np, buf, b); + np[b] = '\0'; // Log message rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr, diff --git a/logd/main.cpp b/logd/main.cpp index a876c99cb..9b889838d 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -33,6 +33,8 @@ #include #include +#include + #include #include #include @@ -275,6 +277,45 @@ static bool property_get_bool_svelte(const char *key) { && !property_get_bool("ro.config.low_ram", false)); } +static void readDmesg(LogAudit *al, LogKlog *kl) { + if (!al && !kl) { + return; + } + + int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0); + if (len <= 0) { + return; + } + + len += 1024; // Margin for additional input race or trailing nul + std::unique_ptr buf(new char[len]); + + int rc = klogctl(KLOG_READ_ALL, buf.get(), len); + if (rc <= 0) { + return; + } + + if (rc < len) { + len = rc + 1; + } + buf[len - 1] = '\0'; + + if (kl) { + kl->synchronize(buf.get()); + } + + for (char *ptr = NULL, *tok = buf.get(); + (rc >= 0) && ((tok = log_strtok_r(tok, &ptr))); + tok = NULL) { + if (al) { + rc = al->log(tok); + } + if (kl) { + rc = kl->log(tok); + } + } +} + // Foreground waits for exit of the main persistent threads // that are started here. The threads are created to manage // UNIX domain client sockets for writing, reading and @@ -410,41 +451,16 @@ int main(int argc, char *argv[]) { kl = new LogKlog(logBuf, reader, fdDmesg, fdPmesg, al != NULL); } - if (al || kl) { - int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0); - if (len > 0) { - len++; - char buf[len]; + readDmesg(al, kl); - int rc = klogctl(KLOG_READ_ALL, buf, len); + // failure is an option ... messages are in dmesg (required by standard) - buf[len - 1] = '\0'; + if (kl && kl->startListener()) { + delete kl; + } - if ((rc >= 0) && kl) { - kl->synchronize(buf); - } - - for (char *ptr = NULL, *tok = buf; - (rc >= 0) && ((tok = log_strtok_r(tok, &ptr))); - tok = NULL) { - if (al) { - rc = al->log(tok); - } - if (kl) { - rc = kl->log(tok); - } - } - } - - // failure is an option ... messages are in dmesg (required by standard) - - if (kl && kl->startListener()) { - delete kl; - } - - if (al && al->startListener()) { - delete al; - } + if (al && al->startListener()) { + delete al; } TEMP_FAILURE_RETRY(pause());