liblog: deal with restart of logd
- API change, return -errno on failure for log writing
- ENOTCONN results in a reconnection and a retry of the write
Change-Id: Ib0a90b730edeaa7e3a3c9797e4e1b0c81b6adb0a
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index aa0ad39..9c73dad 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -77,32 +77,78 @@
return (g_log_status == kLogAvailable);
}
+/* 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;
}
+/* log_init_lock assumed */
+static int __write_to_log_initialize()
+{
+ int i, ret = 0;
+
+#if FAKE_LOG_DEVICE
+ for (i = 0; i < LOG_ID_MAX; i++) {
+ char buf[sizeof("/dev/log_system")];
+ snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
+ log_fds[i] = fakeLogOpen(buf, O_WRONLY);
+ }
+#else
+ if (logd_fd >= 0) {
+ i = logd_fd;
+ logd_fd = -1;
+ close(i);
+ }
+
+ i = socket(PF_UNIX, SOCK_DGRAM, 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) {
+ ret = -errno;
+ close(i);
+ i = -1;
+ }
+ }
+ logd_fd = i;
+#endif
+
+ return ret;
+}
+
static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec, size_t nr)
{
-#if FAKE_LOG_DEVICE
ssize_t ret;
+#if FAKE_LOG_DEVICE
int log_fd;
if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
log_fd = log_fds[(int)log_id];
} else {
- return EBADF;
+ return -EBADF;
}
do {
ret = fakeLogWritev(log_fd, vec, nr);
- } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ } while (ret == -EINTR);
return ret;
#else
- if (logd_fd == -1) {
- return -1;
- }
if (getuid() == AID_LOGD) {
/*
* ignore log messages we send to ourself.
@@ -111,6 +157,11 @@
*/
return 0;
}
+
+ if (logd_fd < 0) {
+ return -EBADF;
+ }
+
/*
* struct {
* // what we provide
@@ -155,8 +206,35 @@
newVec[i].iov_len = vec[i-header_length].iov_len;
}
- /* The write below could be lost, but will never block. */
- return writev(logd_fd, newVec, nr + header_length);
+ /*
+ * The write below could be lost, but will never block.
+ *
+ * ENOTCONN occurs if logd dies.
+ * EAGAIN occurs if logd is overloaded.
+ */
+ ret = writev(logd_fd, newVec, nr + header_length);
+ if (ret < 0) {
+ ret = -errno;
+ if (ret == -ENOTCONN) {
+#ifdef HAVE_PTHREADS
+ pthread_mutex_lock(&log_init_lock);
+#endif
+ ret = __write_to_log_initialize();
+#ifdef HAVE_PTHREADS
+ pthread_mutex_unlock(&log_init_lock);
+#endif
+
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = writev(logd_fd, newVec, nr + header_length);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ }
+ }
+ return ret;
#endif
}
@@ -184,35 +262,17 @@
#endif
if (write_to_log == __write_to_log_init) {
- write_to_log = __write_to_log_kernel;
+ int ret;
-#if FAKE_LOG_DEVICE
- int i;
- for (i = 0; i < LOG_ID_MAX; i++) {
- char buf[sizeof("/dev/log_system")];
- snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
- log_fds[i] = fakeLogOpen(buf, O_WRONLY);
- }
-#else
- int sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (sock != -1) {
- if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
- /* NB: Loss of content */
- close(sock);
- sock = -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");
-
- connect(sock, (struct sockaddr *)&un, sizeof(struct sockaddr_un));
- }
- } else {
- write_to_log = __write_to_log_null;
- }
- logd_fd = sock;
+ ret = __write_to_log_initialize();
+ if (ret < 0) {
+#ifdef HAVE_PTHREADS
+ pthread_mutex_unlock(&log_init_lock);
#endif
+ return ret;
+ }
+
+ write_to_log = __write_to_log_kernel;
}
#ifdef HAVE_PTHREADS
@@ -242,7 +302,7 @@
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS")) {
log_id = LOG_ID_RADIO;
- // Inform third party apps/ril/radio.. to use Rlog or RLOG
+ /* 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;
}
@@ -277,7 +337,7 @@
!strcmp(tag, "PHONE") ||
!strcmp(tag, "SMS"))) {
bufID = LOG_ID_RADIO;
- // Inform third party apps/ril/radio.. to use Rlog or RLOG
+ /* 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;
}
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index 32a202b..5ef349b 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -95,12 +95,15 @@
if (/*(int)log_id >= 0 &&*/ (int)log_id < (int)LOG_ID_MAX) {
log_fd = log_fds[(int)log_id];
} else {
- return EBADF;
+ return -EBADF;
}
do {
ret = log_writev(log_fd, vec, nr);
- } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ ret = -errno;
+ }
+ } while (ret == -EINTR);
return ret;
}