diff options
Diffstat (limited to 'liblog/logd_write.c')
-rw-r--r-- | liblog/logd_write.c | 239 |
1 files changed, 127 insertions, 112 deletions
diff --git a/liblog/logd_write.c b/liblog/logd_write.c index b2668ce..c62a246 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -13,12 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#if (FAKE_LOG_DEVICE == 0) +#include <endian.h> +#endif #include <errno.h> #include <fcntl.h> -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) #include <pthread.h> #endif #include <stdarg.h> +#include <stdatomic.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -39,6 +43,7 @@ #include <log/logger.h> #include <log/log_read.h> #include <private/android_filesystem_config.h> +#include <private/android_logger.h> #define LOG_BUF_SIZE 1024 @@ -49,7 +54,7 @@ static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr); static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init; -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; #endif @@ -61,6 +66,7 @@ static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER; static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 }; #else static int logd_fd = -1; +static int pstore_fd = -1; #endif /* @@ -71,6 +77,7 @@ static int logd_fd = -1; static enum { kLogUninitialized, kLogNotAvailable, kLogAvailable } g_log_status = kLogUninitialized; + int __android_log_dev_available(void) { if (g_log_status == kLogUninitialized) { @@ -83,15 +90,6 @@ int __android_log_dev_available(void) return (g_log_status == kLogAvailable); } -#if !FAKE_LOG_DEVICE -/* give up, resources too limited */ -static int __write_to_log_null(log_id_t log_fd __unused, struct iovec *vec __unused, - size_t nr __unused) -{ - return -1; -} -#endif - /* log_init_lock assumed */ static int __write_to_log_initialize() { @@ -104,40 +102,38 @@ static int __write_to_log_initialize() log_fds[i] = fakeLogOpen(buf, O_WRONLY); } #else - if (logd_fd >= 0) { - i = logd_fd; - logd_fd = -1; - close(i); + if (pstore_fd < 0) { + pstore_fd = TEMP_FAILURE_RETRY(open("/dev/pmsg0", O_WRONLY)); } - i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (i < 0) { - ret = -errno; - write_to_log = __write_to_log_null; - } else if (fcntl(i, F_SETFL, O_NONBLOCK) < 0) { - ret = -errno; - close(i); - i = -1; - write_to_log = __write_to_log_null; - } 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 (connect(i, (struct sockaddr *)&un, sizeof(struct sockaddr_un)) < 0) { + if (logd_fd < 0) { + i = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)); + if (i < 0) { + ret = -errno; + } else if (TEMP_FAILURE_RETRY(fcntl(i, F_SETFL, O_NONBLOCK)) < 0) { ret = -errno; close(i); - i = -1; + } 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(i, (struct sockaddr *)&un, + sizeof(struct sockaddr_un))) < 0) { + ret = -errno; + close(i); + } else { + logd_fd = i; + } } } - logd_fd = i; #endif return ret; } -static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) +static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) { ssize_t ret; #if FAKE_LOG_DEVICE @@ -155,37 +151,32 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) } } while (ret == -EINTR); #else - static const unsigned header_length = 3; + static const unsigned header_length = 2; struct iovec newVec[nr + header_length]; - typeof_log_id_t log_id_buf; - uint16_t tid; + android_log_header_t header; + android_pmsg_log_header_t pmsg_header; struct timespec ts; - log_time realtime_ts; 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 (!nr) { + return -EINVAL; + } if (last_uid == AID_ROOT) { /* have we called to get the UID yet? */ last_uid = getuid(); } - if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ - /* - * 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; - } - - if (logd_fd < 0) { - return -EBADF; + if (last_pid == (pid_t) -1) { + last_pid = getpid(); } - /* * struct { - * // what we provide - * typeof_log_id_t log_id; - * u16 tid; - * log_time realtime; + * // what we provide to pstore + * android_pmsg_log_header_t pmsg_header; + * // what we provide to socket + * android_log_header_t header; * // caller provides * union { * struct { @@ -201,18 +192,42 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) */ clock_gettime(CLOCK_REALTIME, &ts); - realtime_ts.tv_sec = ts.tv_sec; - realtime_ts.tv_nsec = ts.tv_nsec; - log_id_buf = log_id; - tid = gettid(); + pmsg_header.magic = LOGGER_MAGIC; + pmsg_header.len = sizeof(pmsg_header) + sizeof(header); + pmsg_header.uid = last_uid; + pmsg_header.pid = last_pid; + + header.tid = gettid(); + header.realtime.tv_sec = ts.tv_sec; + header.realtime.tv_nsec = ts.tv_nsec; + + newVec[0].iov_base = (unsigned char *) &pmsg_header; + newVec[0].iov_len = sizeof(pmsg_header); + 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); + } + } + } - newVec[0].iov_base = (unsigned char *) &log_id_buf; - newVec[0].iov_len = sizeof_log_id_t; - newVec[1].iov_base = (unsigned char *) &tid; - newVec[1].iov_len = sizeof(tid); - newVec[2].iov_base = (unsigned char *) &realtime_ts; - newVec[2].iov_len = sizeof(log_time); + 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; @@ -223,25 +238,48 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) if (newVec[i].iov_len) { ++i; } + payload_size = LOGGER_ENTRY_MAX_PAYLOAD; break; } } + pmsg_header.len += payload_size; + + if (pstore_fd >= 0) { + TEMP_FAILURE_RETRY(writev(pstore_fd, newVec, i)); + } + + if (last_uid == AID_LOGD) { /* logd, after initialization and priv drop */ + /* + * 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; + } + + if (logd_fd < 0) { + return -EBADF; + } /* * The write below could be lost, but will never block. * + * To logd, we drop the pmsg_header + * * ENOTCONN occurs if logd dies. * EAGAIN occurs if logd is overloaded. */ - ret = writev(logd_fd, newVec, i); + ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); if (ret < 0) { ret = -errno; if (ret == -ENOTCONN) { -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) pthread_mutex_lock(&log_init_lock); #endif + close(logd_fd); + logd_fd = -1; ret = __write_to_log_initialize(); -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) pthread_mutex_unlock(&log_init_lock); #endif @@ -249,15 +287,17 @@ static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr) return ret; } - ret = writev(logd_fd, newVec, nr + header_length); + ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, i - 1)); if (ret < 0) { ret = -errno; } } } - if (ret > (ssize_t)(sizeof_log_id_t + sizeof(tid) + sizeof(log_time))) { - ret -= sizeof_log_id_t + sizeof(tid) + sizeof(log_time); + if (ret > (ssize_t)sizeof(header)) { + ret -= sizeof(header); + } else if (ret == -EAGAIN) { + atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); } #endif @@ -284,7 +324,7 @@ const char *android_log_id_to_name(log_id_t log_id) static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) { -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) pthread_mutex_lock(&log_init_lock); #endif @@ -293,16 +333,21 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) ret = __write_to_log_initialize(); if (ret < 0) { -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) pthread_mutex_unlock(&log_init_lock); #endif +#if (FAKE_LOG_DEVICE == 0) + if (pstore_fd >= 0) { + __write_to_log_daemon(log_id, vec, nr); + } +#endif return ret; } - write_to_log = __write_to_log_kernel; + write_to_log = __write_to_log_daemon; } -#ifdef HAVE_PTHREADS +#if !defined(_WIN32) pthread_mutex_unlock(&log_init_lock); #endif @@ -311,43 +356,7 @@ static int __write_to_log_init(log_id_t log_id, struct iovec *vec, size_t nr) int __android_log_write(int prio, const char *tag, const char *msg) { - struct iovec vec[3]; - log_id_t log_id = LOG_ID_MAIN; - char tmp_tag[32]; - - if (!tag) - tag = ""; - - /* XXX: This needs to go! */ - if (!strcmp(tag, "HTC_RIL") || - !strncmp(tag, "RIL", 3) || /* Any log tag with "RIL" as the prefix */ - !strncmp(tag, "IMS", 3) || /* Any log tag with "IMS" as the prefix */ - !strcmp(tag, "AT") || - !strcmp(tag, "GSM") || - !strcmp(tag, "STK") || - !strcmp(tag, "CDMA") || - !strcmp(tag, "PHONE") || - !strcmp(tag, "SMS")) { - log_id = LOG_ID_RADIO; - /* Inform third party apps/ril/radio.. to use Rlog or RLOG */ - snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag); - tag = tmp_tag; - } - -#if __BIONIC__ - if (prio == ANDROID_LOG_FATAL) { - android_set_abort_message(msg); - } -#endif - - vec[0].iov_base = (unsigned char *) &prio; - vec[0].iov_len = 1; - vec[1].iov_base = (void *) tag; - vec[1].iov_len = strlen(tag) + 1; - vec[2].iov_base = (void *) msg; - vec[2].iov_len = strlen(msg) + 1; - - return write_to_log(log_id, vec, 3); + return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg); } int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg) @@ -375,6 +384,12 @@ int __android_log_buf_write(int bufID, int prio, const char *tag, const char *ms tag = tmp_tag; } +#if __BIONIC__ + if (prio == ANDROID_LOG_FATAL) { + android_set_abort_message(msg); + } +#endif + vec[0].iov_base = (unsigned char *) &prio; vec[0].iov_len = 1; vec[1].iov_base = (void *) tag; @@ -440,7 +455,7 @@ void __android_log_assert(const char *cond, const char *tag, } __android_log_write(ANDROID_LOG_FATAL, tag, buf); - __builtin_trap(); /* trap so we have a chance to debug the situation */ + abort(); /* abort so we have a chance to debug the situation */ /* NOTREACHED */ } |