liblog: Instrument logging of logd write drops
- If logger system is prostrated, send an event message with the
liblog tag from the associated UID and PID with a count of
dropped messages once logging is resumed.
- Added to the README a description of the error return values.
- Describe in the README the appropriate mitigations for dropped
messages.
- If the caller sees this message, then
/proc/sys/net/unix/max_dgram_qlen is likely too small
Change-Id: Iaf387b9e5e1b6aa93bebc7481f9e8353732e3229
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 0208c73..c8a6162 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#if !defined(_WIN32)
#include <pthread.h>
#endif
#include <stdarg.h>
+#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -172,6 +174,7 @@
size_t i, payload_size;
static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
static pid_t last_pid = (pid_t) -1;
+ static atomic_int_fast32_t dropped;
if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */
last_uid = getuid();
@@ -206,7 +209,6 @@
pmsg_header.uid = last_uid;
pmsg_header.pid = last_pid;
- header.id = log_id;
header.tid = gettid();
header.realtime.tv_sec = ts.tv_sec;
header.realtime.tv_nsec = ts.tv_nsec;
@@ -216,6 +218,28 @@
newVec[1].iov_base = (unsigned char *) &header;
newVec[1].iov_len = sizeof(header);
+ if (logd_fd > 0) {
+ int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
+ if (snapshot) {
+ android_log_event_int_t buffer;
+
+ header.id = LOG_ID_EVENTS;
+ buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+ buffer.payload.type = EVENT_TYPE_INT;
+ buffer.payload.data = htole32(snapshot);
+
+ newVec[2].iov_base = &buffer;
+ newVec[2].iov_len = sizeof(buffer);
+
+ ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
+ if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+ atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
+ }
+ }
+ }
+
+ header.id = log_id;
+
for (payload_size = 0, i = header_length; i < nr + header_length; i++) {
newVec[i].iov_base = vec[i - header_length].iov_base;
payload_size += newVec[i].iov_len = vec[i - header_length].iov_len;
@@ -281,6 +305,8 @@
if (ret > (ssize_t)sizeof(header)) {
ret -= sizeof(header);
+ } else if (ret == -EAGAIN) {
+ atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
}
#endif