diff options
Diffstat (limited to 'liblog/logd_writer.c')
-rw-r--r-- | liblog/logd_writer.c | 427 |
1 files changed, 209 insertions, 218 deletions
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.c index 12b797dae..e0e3ecaa1 100644 --- a/liblog/logd_writer.c +++ b/liblog/logd_writer.c @@ -24,9 +24,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> -#include <sys/socket.h> #include <sys/un.h> #include <time.h> #include <unistd.h> @@ -40,260 +40,251 @@ #include "logger.h" /* branchless on many architectures. */ -#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y)))) +#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y)))) static int logdAvailable(log_id_t LogId); static int logdOpen(); static void logdClose(); -static int logdWrite(log_id_t logId, struct timespec *ts, - struct iovec *vec, size_t nr); +static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, + size_t nr); LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = { - .node = { &logdLoggerWrite.node, &logdLoggerWrite.node }, - .context.sock = -EBADF, - .name = "logd", - .available = logdAvailable, - .open = logdOpen, - .close = logdClose, - .write = logdWrite, + .node = { &logdLoggerWrite.node, &logdLoggerWrite.node }, + .context.sock = -EBADF, + .name = "logd", + .available = logdAvailable, + .open = logdOpen, + .close = logdClose, + .write = logdWrite, }; /* log_init_lock assumed */ -static int logdOpen() -{ - int i, ret = 0; - - i = atomic_load(&logdLoggerWrite.context.sock); - if (i < 0) { - int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | - SOCK_CLOEXEC | - SOCK_NONBLOCK, 0)); - if (sock < 0) { - ret = -errno; - } else { - struct sockaddr_un un; - memset(&un, 0, sizeof(struct sockaddr_un)); - un.sun_family = AF_UNIX; - strcpy(un.sun_path, "/dev/socket/logdw"); - - if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr *)&un, - sizeof(struct sockaddr_un))) < 0) { - ret = -errno; - switch (ret) { - case -ENOTCONN: - case -ECONNREFUSED: - case -ENOENT: - i = atomic_exchange(&logdLoggerWrite.context.sock, ret); - /* FALLTHRU */ - default: - break; - } - close(sock); - } else { - ret = atomic_exchange(&logdLoggerWrite.context.sock, sock); - if ((ret >= 0) && (ret != sock)) { - close(ret); - } - ret = 0; - } +static int logdOpen() { + int i, ret = 0; + + i = atomic_load(&logdLoggerWrite.context.sock); + if (i < 0) { + int sock = TEMP_FAILURE_RETRY( + socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)); + if (sock < 0) { + ret = -errno; + } else { + struct sockaddr_un un; + memset(&un, 0, sizeof(struct sockaddr_un)); + un.sun_family = AF_UNIX; + strcpy(un.sun_path, "/dev/socket/logdw"); + + if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un, + sizeof(struct sockaddr_un))) < 0) { + ret = -errno; + switch (ret) { + case -ENOTCONN: + case -ECONNREFUSED: + case -ENOENT: + i = atomic_exchange(&logdLoggerWrite.context.sock, ret); + /* FALLTHRU */ + default: + break; } + close(sock); + } else { + ret = atomic_exchange(&logdLoggerWrite.context.sock, sock); + if ((ret >= 0) && (ret != sock)) { + close(ret); + } + ret = 0; + } } + } - return ret; + return ret; } -static void __logdClose(int negative_errno) -{ - int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno); - if (sock >= 0) { - close(sock); - } +static void __logdClose(int negative_errno) { + int sock = atomic_exchange(&logdLoggerWrite.context.sock, negative_errno); + if (sock >= 0) { + close(sock); + } } -static void logdClose() -{ - __logdClose(-EBADF); +static void logdClose() { + __logdClose(-EBADF); } -static int logdAvailable(log_id_t logId) -{ - if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) { - return -EINVAL; +static int logdAvailable(log_id_t logId) { + if (logId >= LOG_ID_MAX || logId == LOG_ID_KERNEL) { + return -EINVAL; + } + if (atomic_load(&logdLoggerWrite.context.sock) < 0) { + if (access("/dev/socket/logdw", W_OK) == 0) { + return 0; } - if (atomic_load(&logdLoggerWrite.context.sock) < 0) { - if (access("/dev/socket/logdw", W_OK) == 0) { - return 0; - } - return -EBADF; - } - return 1; + return -EBADF; + } + return 1; } -static int logdWrite(log_id_t logId, struct timespec *ts, - struct iovec *vec, size_t nr) -{ - ssize_t ret; - int sock; - static const unsigned headerLength = 1; - struct iovec newVec[nr + headerLength]; - android_log_header_t header; - size_t i, payloadSize; - static atomic_int_fast32_t dropped; - static atomic_int_fast32_t droppedSecurity; - - sock = atomic_load(&logdLoggerWrite.context.sock); - if (sock < 0) switch (sock) { - case -ENOTCONN: - case -ECONNREFUSED: - case -ENOENT: +static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, + size_t nr) { + ssize_t ret; + int sock; + static const unsigned headerLength = 1; + struct iovec newVec[nr + headerLength]; + android_log_header_t header; + size_t i, payloadSize; + static atomic_int_fast32_t dropped; + static atomic_int_fast32_t droppedSecurity; + + sock = atomic_load(&logdLoggerWrite.context.sock); + if (sock < 0) switch (sock) { + case -ENOTCONN: + case -ECONNREFUSED: + case -ENOENT: break; - default: + default: return -EBADF; } - /* logd, after initialization and priv drop */ - if (__android_log_uid() == AID_LOGD) { - /* - * ignore log messages we send to ourself (logd). - * Such log messages are often generated by libraries we depend on - * which use standard Android logging. - */ - return 0; - } - + /* logd, after initialization and priv drop */ + if (__android_log_uid() == AID_LOGD) { /* - * struct { - * // what we provide to socket - * android_log_header_t header; - * // caller provides - * union { - * struct { - * char prio; - * char payload[]; - * } string; - * struct { - * uint32_t tag - * char payload[]; - * } binary; - * }; - * }; + * ignore log messages we send to ourself (logd). + * Such log messages are often generated by libraries we depend on + * which use standard Android logging. */ - - header.tid = gettid(); - header.realtime.tv_sec = ts->tv_sec; - header.realtime.tv_nsec = ts->tv_nsec; - - newVec[0].iov_base = (unsigned char *)&header; - newVec[0].iov_len = sizeof(header); - - if (sock >= 0) { - int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, - memory_order_relaxed); - if (snapshot) { - android_log_event_int_t buffer; - - header.id = LOG_ID_SECURITY; - buffer.header.tag = htole32(LIBLOG_LOG_TAG); - buffer.payload.type = EVENT_TYPE_INT; - buffer.payload.data = htole32(snapshot); - - newVec[headerLength].iov_base = &buffer; - newVec[headerLength].iov_len = sizeof(buffer); - - ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2)); - if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { - atomic_fetch_add_explicit(&droppedSecurity, snapshot, - memory_order_relaxed); - } - } - snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed); - if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, - "liblog", - strlen("liblog"), - ANDROID_LOG_VERBOSE)) { - 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[headerLength].iov_base = &buffer; - newVec[headerLength].iov_len = sizeof(buffer); - - ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2)); - if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { - atomic_fetch_add_explicit(&dropped, snapshot, - memory_order_relaxed); - } - } + return 0; + } + + /* + * struct { + * // what we provide to socket + * android_log_header_t header; + * // caller provides + * union { + * struct { + * char prio; + * char payload[]; + * } string; + * struct { + * uint32_t tag + * char payload[]; + * } binary; + * }; + * }; + */ + + header.tid = gettid(); + header.realtime.tv_sec = ts->tv_sec; + header.realtime.tv_nsec = ts->tv_nsec; + + newVec[0].iov_base = (unsigned char*)&header; + newVec[0].iov_len = sizeof(header); + + if (sock >= 0) { + int32_t snapshot = + atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed); + if (snapshot) { + android_log_event_int_t buffer; + + header.id = LOG_ID_SECURITY; + buffer.header.tag = htole32(LIBLOG_LOG_TAG); + buffer.payload.type = EVENT_TYPE_INT; + buffer.payload.data = htole32(snapshot); + + newVec[headerLength].iov_base = &buffer; + newVec[headerLength].iov_len = sizeof(buffer); + + ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2)); + if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { + atomic_fetch_add_explicit(&droppedSecurity, snapshot, + memory_order_relaxed); + } + } + snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed); + if (snapshot && + __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", + strlen("liblog"), ANDROID_LOG_VERBOSE)) { + 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[headerLength].iov_base = &buffer; + newVec[headerLength].iov_len = sizeof(buffer); + + ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2)); + if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { + atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed); + } } + } - header.id = logId; + header.id = logId; - for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) { - newVec[i].iov_base = vec[i - headerLength].iov_base; - payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len; + for (payloadSize = 0, i = headerLength; i < nr + headerLength; i++) { + newVec[i].iov_base = vec[i - headerLength].iov_base; + payloadSize += newVec[i].iov_len = vec[i - headerLength].iov_len; - if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) { - newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD; - if (newVec[i].iov_len) { - ++i; - } - break; - } + if (payloadSize > LOGGER_ENTRY_MAX_PAYLOAD) { + newVec[i].iov_len -= payloadSize - LOGGER_ENTRY_MAX_PAYLOAD; + if (newVec[i].iov_len) { + ++i; + } + break; } - - /* - * The write below could be lost, but will never block. - * - * ENOTCONN occurs if logd has died. - * ENOENT occurs if logd is not running and socket is missing. - * ECONNREFUSED occurs if we can not reconnect to logd. - * EAGAIN occurs if logd is overloaded. - */ - if (sock < 0) { - ret = sock; - } else { - ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i)); - if (ret < 0) { - ret = -errno; - } + } + + /* + * The write below could be lost, but will never block. + * + * ENOTCONN occurs if logd has died. + * ENOENT occurs if logd is not running and socket is missing. + * ECONNREFUSED occurs if we can not reconnect to logd. + * EAGAIN occurs if logd is overloaded. + */ + if (sock < 0) { + ret = sock; + } else { + ret = TEMP_FAILURE_RETRY(writev(sock, newVec, i)); + if (ret < 0) { + ret = -errno; } - switch(ret) { + } + switch (ret) { case -ENOTCONN: case -ECONNREFUSED: case -ENOENT: - if (__android_log_trylock()) { - return ret; /* in a signal handler? try again when less stressed */ - } - __logdClose(ret); - ret = logdOpen(); - __android_log_unlock(); - - if (ret < 0) { - return ret; - } - - ret = TEMP_FAILURE_RETRY(writev( - atomic_load(&logdLoggerWrite.context.sock), newVec, i)); - if (ret < 0) { - ret = -errno; - } - /* FALLTHRU */ + if (__android_log_trylock()) { + return ret; /* in a signal handler? try again when less stressed */ + } + __logdClose(ret); + ret = logdOpen(); + __android_log_unlock(); + + if (ret < 0) { + return ret; + } + + ret = TEMP_FAILURE_RETRY( + writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i)); + if (ret < 0) { + ret = -errno; + } + /* FALLTHRU */ default: - break; - } - - if (ret > (ssize_t)sizeof(header)) { - ret -= sizeof(header); - } else if (ret == -EAGAIN) { - atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); - if (logId == LOG_ID_SECURITY) { - atomic_fetch_add_explicit(&droppedSecurity, 1, - memory_order_relaxed); - } + break; + } + + if (ret > (ssize_t)sizeof(header)) { + ret -= sizeof(header); + } else if (ret == -EAGAIN) { + atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); + if (logId == LOG_ID_SECURITY) { + atomic_fetch_add_explicit(&droppedSecurity, 1, memory_order_relaxed); } + } - return ret; + return ret; } |