liblog: add a timeout for logd command socket operations
Add a 2s timeout for logd command socket operations:
android_logger_clear
android_logger_get_log_readable_size
android_logger_get_log_size
android_logger_set_log_size
android_logger_get_statistics
android_logger_get_prune_list
android_logger_set_prune_list
That correspond to:
logcat -c
logcat -g
logcat -G
logcat -S
logcat -p
logcat -P
These operations should return immediately in typical circumstances,
but if logd is stuck, they would otherwise block indefinitely. This
allows the commands to gracefully timeout instead.
Test: kill -s STOP `pidof logd`; logcat -g (and other options)
times out appropriately
Test: logcat -g (and other options) work successfully otherwise
Change-Id: I6c4671a9b3daa4a454c0a14ae7d0b7d3b08be77a
diff --git a/liblog/logd_reader.cpp b/liblog/logd_reader.cpp
index 82ed6b2..7123f60 100644
--- a/liblog/logd_reader.cpp
+++ b/liblog/logd_reader.cpp
@@ -41,7 +41,7 @@
// Connects to /dev/socket/<name> and returns the associated fd or returns -1 on error.
// O_CLOEXEC is always set.
-static int socket_local_client(const std::string& name, int type) {
+static int socket_local_client(const std::string& name, int type, bool timeout) {
sockaddr_un addr = {.sun_family = AF_LOCAL};
std::string path = "/dev/socket/" + name;
@@ -55,6 +55,18 @@
return -1;
}
+ if (timeout) {
+ // Sending and receiving messages should be instantaneous, but we don't want to wait forever if
+ // logd is hung, so we set a gracious 2s timeout.
+ struct timeval t = {2, 0};
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t)) == -1) {
+ return -1;
+ }
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t)) == -1) {
+ return -1;
+ }
+ }
+
if (connect(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
close(fd);
return -1;
@@ -69,7 +81,7 @@
size_t len;
char* cp;
int errno_save = 0;
- int sock = socket_local_client("logd", SOCK_STREAM);
+ int sock = socket_local_client("logd", SOCK_STREAM, true);
if (sock < 0) {
return sock;
}
@@ -268,7 +280,7 @@
return sock;
}
- sock = socket_local_client("logdr", SOCK_SEQPACKET);
+ sock = socket_local_client("logdr", SOCK_SEQPACKET, false);
if (sock <= 0) {
if ((sock == -1) && errno) {
return -errno;