Merge changes Idaa6699d,Ic7759ef9
am: faf7946bd7

* commit 'faf7946bd79622a6fc564bc2487c21c950c896b1':
  logd: sock_alloc_send_pskb starves pruning
  logd: Allow (some) headers to be individually importable
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index fd45c4a..6a26d00 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -16,7 +16,10 @@
 
 #include <stdlib.h>
 
+#include <private/android_filesystem_config.h>
+
 #include "FlushCommand.h"
+#include "LogBuffer.h"
 #include "LogBufferElement.h"
 #include "LogCommand.h"
 #include "LogReader.h"
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index fffc9ba..230dd11 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -20,10 +20,13 @@
 #include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/prctl.h>
 #include <sys/uio.h>
 #include <syslog.h>
 
+#include <string>
+
 #include <cutils/properties.h>
 #include <log/logger.h>
 #include <private/android_filesystem_config.h>
@@ -31,7 +34,9 @@
 
 #include "libaudit.h"
 #include "LogAudit.h"
+#include "LogBuffer.h"
 #include "LogKlog.h"
+#include "LogReader.h"
 
 #ifndef AUDITD_ENFORCE_INTEGRITY
 #define AUDITD_ENFORCE_INTEGRITY false
diff --git a/logd/LogAudit.h b/logd/LogAudit.h
index 455ed58..3a84541 100644
--- a/logd/LogAudit.h
+++ b/logd/LogAudit.h
@@ -18,7 +18,10 @@
 #define _LOGD_LOG_AUDIT_H__
 
 #include <sysutils/SocketListener.h>
-#include "LogReader.h"
+
+#include "LogBuffer.h"
+
+class LogReader;
 
 class LogAudit : public SocketListener {
     LogBuffer *logbuf;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index fde9ad7..eb5194c 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -25,9 +25,11 @@
 #include <log/logger.h>
 #include <private/android_logger.h>
 
+#include "LogBuffer.h"
 #include "LogBufferElement.h"
 #include "LogCommand.h"
 #include "LogReader.h"
+#include "LogUtils.h"
 
 const uint64_t LogBufferElement::FLUSH_ERROR(0);
 atomic_int_fast64_t LogBufferElement::sequence(1);
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 9690489..ac2b128 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -20,13 +20,16 @@
 #include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/prctl.h>
 #include <sys/uio.h>
 #include <syslog.h>
 
 #include <log/logger.h>
 
+#include "LogBuffer.h"
 #include "LogKlog.h"
+#include "LogReader.h"
 
 #define KMSG_PRIORITY(PRI)           \
     '<',                             \
diff --git a/logd/LogKlog.h b/logd/LogKlog.h
index 3c8cc87..ee73b71 100644
--- a/logd/LogKlog.h
+++ b/logd/LogKlog.h
@@ -19,10 +19,12 @@
 
 #include <sysutils/SocketListener.h>
 #include <log/log_read.h>
-#include "LogReader.h"
 
 char *log_strntok_r(char *s, size_t *len, char **saveptr, size_t *sublen);
 
+class LogBuffer;
+class LogReader;
+
 class LogKlog : public SocketListener {
     LogBuffer *logbuf;
     LogReader *reader;
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 846dd7c..39dd227 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -27,6 +27,7 @@
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 
+#include "LogBuffer.h"
 #include "LogListener.h"
 #include "LogUtils.h"
 
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 667a3f2..2c07984 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -18,11 +18,15 @@
 #include <poll.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 
 #include <cutils/sockets.h>
 
-#include "LogReader.h"
 #include "FlushCommand.h"
+#include "LogBuffer.h"
+#include "LogBufferElement.h"
+#include "LogReader.h"
+#include "LogUtils.h"
 
 LogReader::LogReader(LogBuffer *logbuf) :
         SocketListener(getLogSocket(), true),
@@ -176,6 +180,11 @@
     }
 
     FlushCommand command(*this, nonBlock, tail, logMask, pid, sequence, timeout);
+
+    // Set acceptable upper limit to wait for slow reader processing b/27242723
+    struct timeval t = { LOGD_SNDTIMEO, 0 };
+    setsockopt(cli->getSocket(), SOL_SOCKET, SO_SNDTIMEO, (const char *)&t, sizeof(t));
+
     command.runSocketCommand(cli);
     return true;
 }
diff --git a/logd/LogReader.h b/logd/LogReader.h
index 91559a3..98674b8 100644
--- a/logd/LogReader.h
+++ b/logd/LogReader.h
@@ -18,8 +18,10 @@
 #define _LOGD_LOG_WRITER_H__
 
 #include <sysutils/SocketListener.h>
-#include "LogBuffer.h"
-#include "LogTimes.h"
+
+#define LOGD_SNDTIMEO 32
+
+class LogBuffer;
 
 class LogReader : public SocketListener {
     LogBuffer &mLogbuf;
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index 1117088..f5969df 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -27,6 +27,7 @@
 #include <log/log.h>
 
 class LogReader;
+class LogBufferElement;
 
 class LogTimeEntry {
     static pthread_mutex_t timesLock;
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index de19790..2014374 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -30,6 +30,8 @@
 #include <log/log.h>
 #include <log/logger.h>
 
+#include "../LogReader.h" // pickup LOGD_SNDTIMEO
+
 /*
  * returns statistics
  */
@@ -253,6 +255,9 @@
         fprintf(stderr, "lid=crash ");
         break;
     case 5:
+        fprintf(stderr, "lid=security ");
+        break;
+    case 6:
         fprintf(stderr, "lid=kernel ");
         break;
     default:
@@ -710,3 +715,56 @@
     EXPECT_TRUE(content_timeout);
     EXPECT_NE(0U, alarm_timeout);
 }
+
+// b/27242723 confirmed fixed
+TEST(logd, SNDTIMEO) {
+    static const unsigned sndtimeo = LOGD_SNDTIMEO; // <sigh> it has to be done!
+    static const unsigned sleep_time = sndtimeo + 3;
+    static const unsigned alarm_time = sleep_time + 5;
+
+    int fd;
+
+    ASSERT_TRUE((fd = socket_local_client("logdr",
+                                 ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                 SOCK_SEQPACKET)) > 0);
+
+    struct sigaction ignore, old_sigaction;
+    memset(&ignore, 0, sizeof(ignore));
+    ignore.sa_handler = caught_signal;
+    sigemptyset(&ignore.sa_mask);
+    sigaction(SIGALRM, &ignore, &old_sigaction);
+    unsigned int old_alarm = alarm(alarm_time);
+
+    static const char ask[] = "stream lids=0,1,2,3,4,5,6"; // all sources
+    bool reader_requested = write(fd, ask, sizeof(ask)) == sizeof(ask);
+    EXPECT_TRUE(reader_requested);
+
+    log_msg msg;
+    bool read_one = recv(fd, msg.buf, sizeof(msg), 0) > 0;
+
+    EXPECT_TRUE(read_one);
+    if (read_one) {
+        dump_log_msg("user", &msg, 3, -1);
+    }
+
+    fprintf (stderr, "Sleep for >%d seconds logd SO_SNDTIMEO ...\n", sndtimeo);
+    sleep(sleep_time);
+
+    // flush will block if we did not trigger. if it did, last entry returns 0
+    int recv_ret;
+    do {
+        recv_ret = recv(fd, msg.buf, sizeof(msg), 0);
+    } while (recv_ret > 0);
+    int save_errno = (recv_ret < 0) ? errno : 0;
+
+    EXPECT_NE(0U, alarm(old_alarm));
+    sigaction(SIGALRM, &old_sigaction, NULL);
+
+    EXPECT_EQ(0, recv_ret);
+    if (recv_ret > 0) {
+        dump_log_msg("user", &msg, 3, -1);
+    }
+    EXPECT_EQ(0, save_errno);
+
+    close(fd);
+}