summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Salyzyn2015-11-06 14:26:52 -0600
committerMark Salyzyn2015-11-12 17:39:04 -0600
commit7a2a3071921b11d7e476862e7f9cbe72be43d0f7 (patch)
tree1fa427048f6f17e5fa144abda6bb1cf4516b10c8 /liblog/fake_log_device.c
parent8ce943b3f6553c1cc707ac725911e70036d05175 (diff)
downloadplatform-system-core-7a2a3071921b11d7e476862e7f9cbe72be43d0f7.tar.gz
platform-system-core-7a2a3071921b11d7e476862e7f9cbe72be43d0f7.tar.xz
platform-system-core-7a2a3071921b11d7e476862e7f9cbe72be43d0f7.zip
liblog: resolve deadlocks
Although ever present, an increased regression introduced with commit b6bee33182cedea49199eb2252b3f3b442899c6d (liblog: logd: support logd.timestamp = monotonic). A signal handler can interrupt in locked context, if log is written in the signal handler, we are in deadlock. Block signals while we are locked. Separate out timestamp lock from is loggable lock to reduce contention situations. Provide a best-guess response if lock would fail in timestamp path. Bug: 25563384 Change-Id: I6dccd6b99ebace1c473c03a785a35c63ed5c6a8a
Diffstat (limited to 'liblog/fake_log_device.c')
-rw-r--r--liblog/fake_log_device.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index 8a8ece250..fcdb6c928 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -24,6 +24,7 @@
24#include <ctype.h> 24#include <ctype.h>
25#include <errno.h> 25#include <errno.h>
26#include <fcntl.h> 26#include <fcntl.h>
27#include <signal.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include <string.h> 29#include <string.h>
29 30
@@ -97,18 +98,33 @@ typedef struct LogState {
97 */ 98 */
98static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER; 99static pthread_mutex_t fakeLogDeviceLock = PTHREAD_MUTEX_INITIALIZER;
99 100
100static void lock() 101static void lock(sigset_t *sigflags)
101{ 102{
103 /*
104 * If we trigger a signal handler in the middle of locked activity and the
105 * signal handler logs a message, we could get into a deadlock state.
106 */
107 sigset_t all;
108
109 sigfillset(&all);
110 pthread_sigmask(SIG_BLOCK, &all, sigflags);
102 pthread_mutex_lock(&fakeLogDeviceLock); 111 pthread_mutex_lock(&fakeLogDeviceLock);
103} 112}
104 113
105static void unlock() 114static void unlock(sigset_t *sigflags)
106{ 115{
107 pthread_mutex_unlock(&fakeLogDeviceLock); 116 pthread_mutex_unlock(&fakeLogDeviceLock);
117 pthread_sigmask(SIG_UNBLOCK, sigflags, NULL);
108} 118}
119
120#define DECLARE_SIGSET(name) sigset_t name
121
109#else // !defined(_WIN32) 122#else // !defined(_WIN32)
110#define lock() ((void)0) 123
111#define unlock() ((void)0) 124#define lock(sigflags) ((void)0)
125#define unlock(sigflags) ((void)0)
126#define DECLARE_SIGSET(name)
127
112#endif // !defined(_WIN32) 128#endif // !defined(_WIN32)
113 129
114 130
@@ -154,8 +170,9 @@ static LogState *fdToLogState(int fd)
154static void deleteFakeFd(int fd) 170static void deleteFakeFd(int fd)
155{ 171{
156 LogState *ls; 172 LogState *ls;
173 DECLARE_SIGSET(sigflags);
157 174
158 lock(); 175 lock(&sigflags);
159 176
160 ls = fdToLogState(fd); 177 ls = fdToLogState(fd);
161 if (ls != NULL) { 178 if (ls != NULL) {
@@ -164,7 +181,7 @@ static void deleteFakeFd(int fd)
164 free(ls); 181 free(ls);
165 } 182 }
166 183
167 unlock(); 184 unlock(&sigflags);
168} 185}
169 186
170/* 187/*
@@ -548,12 +565,13 @@ static void showLog(LogState *state,
548static ssize_t logWritev(int fd, const struct iovec* vector, int count) 565static ssize_t logWritev(int fd, const struct iovec* vector, int count)
549{ 566{
550 LogState* state; 567 LogState* state;
568 DECLARE_SIGSET(sigflags);
551 569
552 /* Make sure that no-one frees the LogState while we're using it. 570 /* Make sure that no-one frees the LogState while we're using it.
553 * Also guarantees that only one thread is in showLog() at a given 571 * Also guarantees that only one thread is in showLog() at a given
554 * time (if it matters). 572 * time (if it matters).
555 */ 573 */
556 lock(); 574 lock(&sigflags);
557 575
558 state = fdToLogState(fd); 576 state = fdToLogState(fd);
559 if (state == NULL) { 577 if (state == NULL) {
@@ -598,10 +616,10 @@ static ssize_t logWritev(int fd, const struct iovec* vector, int count)
598 } 616 }
599 617
600bail: 618bail:
601 unlock(); 619 unlock(&sigflags);
602 return vector[0].iov_len + vector[1].iov_len + vector[2].iov_len; 620 return vector[0].iov_len + vector[1].iov_len + vector[2].iov_len;
603error: 621error:
604 unlock(); 622 unlock(&sigflags);
605 return -1; 623 return -1;
606} 624}
607 625
@@ -621,8 +639,9 @@ static int logOpen(const char* pathName, int flags __unused)
621{ 639{
622 LogState *logState; 640 LogState *logState;
623 int fd = -1; 641 int fd = -1;
642 DECLARE_SIGSET(sigflags);
624 643
625 lock(); 644 lock(&sigflags);
626 645
627 logState = createLogState(); 646 logState = createLogState();
628 if (logState != NULL) { 647 if (logState != NULL) {
@@ -632,7 +651,7 @@ static int logOpen(const char* pathName, int flags __unused)
632 errno = ENFILE; 651 errno = ENFILE;
633 } 652 }
634 653
635 unlock(); 654 unlock(&sigflags);
636 655
637 return fd; 656 return fd;
638} 657}