system/corennnnn
修訂 | 56f7e9719f4b2615426d01baeff0584a7eb88614 (tree) |
---|---|
時間 | 2015-12-22 11:59:30 |
作者 | TraianX Schiau <traianx.schiau@inte...> |
Commiter | Chih-Wei Huang |
logd: Fix pruning
In a scenario in which an on-line (blocking) client is running and
a clean is attempted (logcat -c), the following can be observed:
1) the on-line logger seems to freeze
2) any other clear attempt will have no effect
What is actually happening:
In this case prune function will "instruct" the oldest timeEntry
to skip a huge number (very close to ULONG_MAX) of messages, this
being the cause of 1.
Since the consumer thread will skip all the log entries, mStart
updating will also be skipped. So a new cleaning attempt will have
the same oldest entry, nothing will be done.
Fix description:
a. keep a separated skipAhead count for individual log buffers (log_id_t)
b. update LogTimeEntry::mStart even if the current message is skipped
c. while pruning, only take into account the LogTimeEntrys that are monitoring
d. Reset the skip cont befor the client thtread starts to sleep, at this point
Change-Id: I1b369dc5b02476e633e52578266a644e37e188a5
Signed-off-by: TraianX Schiau <traianx.schiau@intel.com>
@@ -241,7 +241,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { | ||
241 | 241 | LastLogTimes::iterator t = mTimes.begin(); |
242 | 242 | while(t != mTimes.end()) { |
243 | 243 | LogTimeEntry *entry = (*t); |
244 | - if (entry->owned_Locked() | |
244 | + if (entry->owned_Locked() && entry->isWatching(id) | |
245 | 245 | && (!oldest || (oldest->mStart > entry->mStart))) { |
246 | 246 | oldest = entry; |
247 | 247 | } |
@@ -353,7 +353,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { | ||
353 | 353 | // kick a misbehaving log reader client off the island |
354 | 354 | oldest->release_Locked(); |
355 | 355 | } else { |
356 | - oldest->triggerSkip_Locked(pruneRows); | |
356 | + oldest->triggerSkip_Locked(id, pruneRows); | |
357 | 357 | } |
358 | 358 | } |
359 | 359 | break; |
@@ -384,7 +384,7 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { | ||
384 | 384 | // kick a misbehaving log reader client off the island |
385 | 385 | oldest->release_Locked(); |
386 | 386 | } else { |
387 | - oldest->triggerSkip_Locked(pruneRows); | |
387 | + oldest->triggerSkip_Locked(id, pruneRows); | |
388 | 388 | } |
389 | 389 | break; |
390 | 390 | } |
@@ -36,7 +36,6 @@ LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client, | ||
36 | 36 | , mReader(reader) |
37 | 37 | , mLogMask(logMask) |
38 | 38 | , mPid(pid) |
39 | - , skipAhead(0) | |
40 | 39 | , mCount(0) |
41 | 40 | , mTail(tail) |
42 | 41 | , mIndex(0) |
@@ -46,6 +45,7 @@ LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client, | ||
46 | 45 | , mEnd(CLOCK_MONOTONIC) |
47 | 46 | { |
48 | 47 | pthread_cond_init(&threadTriggeredCondition, NULL); |
48 | + cleanSkip_Locked(); | |
49 | 49 | } |
50 | 50 | |
51 | 51 | void LogTimeEntry::startReader_Locked(void) { |
@@ -148,6 +148,8 @@ void *LogTimeEntry::threadStart(void *obj) { | ||
148 | 148 | break; |
149 | 149 | } |
150 | 150 | |
151 | + me->cleanSkip_Locked(); | |
152 | + | |
151 | 153 | pthread_cond_wait(&me->threadTriggeredCondition, ×Lock); |
152 | 154 | } |
153 | 155 |
@@ -169,7 +171,7 @@ bool LogTimeEntry::FilterFirstPass(const LogBufferElement *element, void *obj) { | ||
169 | 171 | } |
170 | 172 | |
171 | 173 | if ((!me->mPid || (me->mPid == element->getPid())) |
172 | - && (me->mLogMask & (1 << element->getLogId()))) { | |
174 | + && (me->isWatching(element->getLogId()))) { | |
173 | 175 | ++me->mCount; |
174 | 176 | } |
175 | 177 |
@@ -184,19 +186,19 @@ bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) | ||
184 | 186 | |
185 | 187 | LogTimeEntry::lock(); |
186 | 188 | |
187 | - if (me->skipAhead) { | |
188 | - me->skipAhead--; | |
189 | + me->mStart = element->getMonotonicTime(); | |
190 | + | |
191 | + if (me->skipAhead[element->getLogId()]) { | |
192 | + me->skipAhead[element->getLogId()]--; | |
189 | 193 | goto skip; |
190 | 194 | } |
191 | 195 | |
192 | - me->mStart = element->getMonotonicTime(); | |
193 | - | |
194 | 196 | // Truncate to close race between first and second pass |
195 | 197 | if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) { |
196 | 198 | goto skip; |
197 | 199 | } |
198 | 200 | |
199 | - if ((me->mLogMask & (1 << element->getLogId())) == 0) { | |
201 | + if (!me->isWatching(element->getLogId())) { | |
200 | 202 | goto skip; |
201 | 203 | } |
202 | 204 |
@@ -223,7 +225,7 @@ bool LogTimeEntry::FilterSecondPass(const LogBufferElement *element, void *obj) | ||
223 | 225 | } |
224 | 226 | |
225 | 227 | ok: |
226 | - if (!me->skipAhead) { | |
228 | + if (!me->skipAhead[element->getLogId()]) { | |
227 | 229 | LogTimeEntry::unlock(); |
228 | 230 | return true; |
229 | 231 | } |
@@ -233,3 +235,9 @@ skip: | ||
233 | 235 | LogTimeEntry::unlock(); |
234 | 236 | return false; |
235 | 237 | } |
238 | + | |
239 | +void LogTimeEntry::cleanSkip_Locked(void) { | |
240 | + for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1)) { | |
241 | + skipAhead[i] = 0; | |
242 | + } | |
243 | +} |
@@ -22,6 +22,7 @@ | ||
22 | 22 | #include <sys/types.h> |
23 | 23 | #include <sysutils/SocketClient.h> |
24 | 24 | #include <utils/List.h> |
25 | +#include <log/log.h> | |
25 | 26 | |
26 | 27 | class LogReader; |
27 | 28 |
@@ -38,7 +39,7 @@ class LogTimeEntry { | ||
38 | 39 | static void threadStop(void *me); |
39 | 40 | const unsigned int mLogMask; |
40 | 41 | const pid_t mPid; |
41 | - unsigned int skipAhead; | |
42 | + unsigned int skipAhead[LOG_ID_MAX]; | |
42 | 43 | unsigned long mCount; |
43 | 44 | unsigned long mTail; |
44 | 45 | unsigned long mIndex; |
@@ -67,7 +68,8 @@ public: | ||
67 | 68 | pthread_cond_signal(&threadTriggeredCondition); |
68 | 69 | } |
69 | 70 | |
70 | - void triggerSkip_Locked(unsigned int skip) { skipAhead = skip; } | |
71 | + void triggerSkip_Locked(log_id_t id, unsigned int skip) { skipAhead[id] = skip; } | |
72 | + void cleanSkip_Locked(void); | |
71 | 73 | |
72 | 74 | // Called after LogTimeEntry removed from list, lock implicitly held |
73 | 75 | void release_Locked(void) { |
@@ -99,7 +101,7 @@ public: | ||
99 | 101 | // No one else is holding a reference to this |
100 | 102 | delete this; |
101 | 103 | } |
102 | - | |
104 | + bool isWatching(log_id_t id) { return (mLogMask & (1<<id)) != 0; } | |
103 | 105 | // flushTo filter callbacks |
104 | 106 | static bool FilterFirstPass(const LogBufferElement *element, void *me); |
105 | 107 | static bool FilterSecondPass(const LogBufferElement *element, void *me); |