blob: 04e531f8613898a7a02bd27c4729fd8f51503dcb [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mark Salyzynb75cce02015-11-30 11:35:56 -080017#include <errno.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070018#include <sys/prctl.h>
19
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -080020#include <private/android_logger.h>
21
Mark Salyzyn0175b072014-02-26 09:50:16 -080022#include "FlushCommand.h"
23#include "LogBuffer.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080024#include "LogReader.h"
Mark Salyzyn501c3732017-03-10 14:31:54 -080025#include "LogTimes.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080026
27pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
28
Mark Salyzyn501c3732017-03-10 14:31:54 -080029LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client,
Mark Salyzyn0175b072014-02-26 09:50:16 -080030 bool nonBlock, unsigned long tail,
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -080031 unsigned int logMask, pid_t pid, log_time start,
Mark Salyzyn501c3732017-03-10 14:31:54 -080032 uint64_t timeout)
33 : mRefCount(1),
34 mRelease(false),
35 mError(false),
36 threadRunning(false),
37 leadingDropped(false),
38 mReader(reader),
39 mLogMask(logMask),
40 mPid(pid),
41 mCount(0),
42 mTail(tail),
43 mIndex(0),
44 mClient(client),
45 mStart(start),
46 mNonBlock(nonBlock),
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -080047 mEnd(log_time(android_log_clockid())) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080048 mTimeout.tv_sec = timeout / NS_PER_SEC;
49 mTimeout.tv_nsec = timeout % NS_PER_SEC;
Mark Salyzyn77187782015-05-12 15:21:31 -070050 pthread_cond_init(&threadTriggeredCondition, NULL);
51 cleanSkip_Locked();
Mark Salyzyna16f7612014-08-07 08:16:52 -070052}
Mark Salyzyn0175b072014-02-26 09:50:16 -080053
54void LogTimeEntry::startReader_Locked(void) {
Mark Salyzyn765f7822014-04-04 12:47:44 -070055 pthread_attr_t attr;
56
Mark Salyzyn0175b072014-02-26 09:50:16 -080057 threadRunning = true;
Mark Salyzyn765f7822014-04-04 12:47:44 -070058
59 if (!pthread_attr_init(&attr)) {
60 if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080061 if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart,
62 this)) {
Mark Salyzyn765f7822014-04-04 12:47:44 -070063 pthread_attr_destroy(&attr);
64 return;
65 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080066 }
Mark Salyzyn765f7822014-04-04 12:47:44 -070067 pthread_attr_destroy(&attr);
Mark Salyzyn0175b072014-02-26 09:50:16 -080068 }
Mark Salyzyn765f7822014-04-04 12:47:44 -070069 threadRunning = false;
70 if (mClient) {
71 mClient->decRef();
72 }
73 decRef_Locked();
Mark Salyzyn0175b072014-02-26 09:50:16 -080074}
75
Mark Salyzyn501c3732017-03-10 14:31:54 -080076void LogTimeEntry::threadStop(void* obj) {
77 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -080078
79 lock();
80
Mark Salyzyn0175b072014-02-26 09:50:16 -080081 if (me->mNonBlock) {
82 me->error_Locked();
83 }
84
Mark Salyzyn501c3732017-03-10 14:31:54 -080085 SocketClient* client = me->mClient;
Mark Salyzyn0175b072014-02-26 09:50:16 -080086
87 if (me->isError_Locked()) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080088 LogReader& reader = me->mReader;
89 LastLogTimes& times = reader.logbuf().mTimes;
Mark Salyzyn0175b072014-02-26 09:50:16 -080090
91 LastLogTimes::iterator it = times.begin();
Mark Salyzyn501c3732017-03-10 14:31:54 -080092 while (it != times.end()) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080093 if (*it == me) {
94 times.erase(it);
Mark Salyzync3484162016-03-01 14:59:32 -080095 me->release_nodelete_Locked();
Mark Salyzyn0175b072014-02-26 09:50:16 -080096 break;
97 }
98 it++;
99 }
100
101 me->mClient = NULL;
102 reader.release(client);
103 }
104
105 if (client) {
106 client->decRef();
107 }
108
Mark Salyzyna16f7612014-08-07 08:16:52 -0700109 me->threadRunning = false;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800110 me->decRef_Locked();
111
112 unlock();
113}
114
Mark Salyzyn501c3732017-03-10 14:31:54 -0800115void* LogTimeEntry::threadStart(void* obj) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700116 prctl(PR_SET_NAME, "logd.reader.per");
117
Mark Salyzyn501c3732017-03-10 14:31:54 -0800118 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800119
120 pthread_cleanup_push(threadStop, obj);
121
Mark Salyzyn501c3732017-03-10 14:31:54 -0800122 SocketClient* client = me->mClient;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800123 if (!client) {
124 me->error();
Mark Salyzyna16f7612014-08-07 08:16:52 -0700125 return NULL;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800126 }
127
Mark Salyzyn501c3732017-03-10 14:31:54 -0800128 LogBuffer& logbuf = me->mReader.logbuf();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800129
130 bool privileged = FlushCommand::hasReadLogs(client);
Mark Salyzyn8fa88962016-01-26 14:32:35 -0800131 bool security = FlushCommand::hasSecurityLogs(client);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800132
Mark Salyzyn047cc072015-06-04 13:35:30 -0700133 me->leadingDropped = true;
134
Mark Salyzyn0175b072014-02-26 09:50:16 -0800135 lock();
136
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -0800137 log_time start = me->mStart;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800138
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700139 while (me->threadRunning && !me->isError_Locked()) {
Mark Salyzynb75cce02015-11-30 11:35:56 -0800140 if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
141 if (pthread_cond_timedwait(&me->threadTriggeredCondition,
Mark Salyzyn501c3732017-03-10 14:31:54 -0800142 &timesLock, &me->mTimeout) == ETIMEDOUT) {
Mark Salyzynb75cce02015-11-30 11:35:56 -0800143 me->mTimeout.tv_sec = 0;
144 me->mTimeout.tv_nsec = 0;
145 }
146 if (!me->threadRunning || me->isError_Locked()) {
147 break;
148 }
149 }
150
Mark Salyzyn0175b072014-02-26 09:50:16 -0800151 unlock();
152
153 if (me->mTail) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800154 logbuf.flushTo(client, start, privileged, security, FilterFirstPass,
155 me);
Mark Salyzyn047cc072015-06-04 13:35:30 -0700156 me->leadingDropped = true;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800157 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800158 start = logbuf.flushTo(client, start, privileged, security,
159 FilterSecondPass, me);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800160
Mark Salyzyna16f7612014-08-07 08:16:52 -0700161 lock();
162
Mark Salyzyn0175b072014-02-26 09:50:16 -0800163 if (start == LogBufferElement::FLUSH_ERROR) {
Mark Salyzyna16f7612014-08-07 08:16:52 -0700164 me->error_Locked();
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700165 break;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800166 }
167
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -0800168 me->mStart = start + log_time(0, 1);
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700169
Mark Salyzyna16f7612014-08-07 08:16:52 -0700170 if (me->mNonBlock || !me->threadRunning || me->isError_Locked()) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800171 break;
172 }
173
TraianX Schiauda6495d2014-12-17 10:53:41 +0200174 me->cleanSkip_Locked();
175
Mark Salyzynb75cce02015-11-30 11:35:56 -0800176 if (!me->mTimeout.tv_sec && !me->mTimeout.tv_nsec) {
177 pthread_cond_wait(&me->threadTriggeredCondition, &timesLock);
178 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800179 }
180
181 unlock();
182
Mark Salyzyn0175b072014-02-26 09:50:16 -0800183 pthread_cleanup_pop(true);
184
185 return NULL;
186}
187
188// A first pass to count the number of elements
Mark Salyzyn501c3732017-03-10 14:31:54 -0800189int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
190 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800191
192 LogTimeEntry::lock();
193
Mark Salyzyn047cc072015-06-04 13:35:30 -0700194 if (me->leadingDropped) {
195 if (element->getDropped()) {
196 LogTimeEntry::unlock();
197 return false;
198 }
199 me->leadingDropped = false;
200 }
201
Mark Salyzyn0175b072014-02-26 09:50:16 -0800202 if (me->mCount == 0) {
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -0800203 me->mStart = element->getRealTime();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800204 }
205
Mark Salyzyn501c3732017-03-10 14:31:54 -0800206 if ((!me->mPid || (me->mPid == element->getPid())) &&
207 (me->isWatching(element->getLogId()))) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800208 ++me->mCount;
209 }
210
211 LogTimeEntry::unlock();
212
213 return false;
214}
215
216// A second pass to send the selected elements
Mark Salyzyn501c3732017-03-10 14:31:54 -0800217int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
218 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800219
220 LogTimeEntry::lock();
221
Mark Salyzyn5a34d6e2017-03-10 08:44:14 -0800222 me->mStart = element->getRealTime();
TraianX Schiauda6495d2014-12-17 10:53:41 +0200223
224 if (me->skipAhead[element->getLogId()]) {
225 me->skipAhead[element->getLogId()]--;
Mark Salyzyn8d7656b2014-06-05 15:58:43 -0700226 goto skip;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800227 }
228
Mark Salyzyn047cc072015-06-04 13:35:30 -0700229 if (me->leadingDropped) {
230 if (element->getDropped()) {
231 goto skip;
232 }
233 me->leadingDropped = false;
234 }
235
Mark Salyzyn0175b072014-02-26 09:50:16 -0800236 // Truncate to close race between first and second pass
237 if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800238 goto stop;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800239 }
240
TraianX Schiauda6495d2014-12-17 10:53:41 +0200241 if (!me->isWatching(element->getLogId())) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800242 goto skip;
243 }
244
245 if (me->mPid && (me->mPid != element->getPid())) {
246 goto skip;
247 }
248
249 if (me->isError_Locked()) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800250 goto stop;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800251 }
252
253 if (!me->mTail) {
254 goto ok;
255 }
256
257 ++me->mIndex;
258
259 if ((me->mCount > me->mTail) && (me->mIndex <= (me->mCount - me->mTail))) {
260 goto skip;
261 }
262
263 if (!me->mNonBlock) {
264 me->mTail = 0;
265 }
266
267ok:
TraianX Schiauda6495d2014-12-17 10:53:41 +0200268 if (!me->skipAhead[element->getLogId()]) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800269 LogTimeEntry::unlock();
270 return true;
271 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800272// FALLTHRU
Mark Salyzyn0175b072014-02-26 09:50:16 -0800273
274skip:
275 LogTimeEntry::unlock();
276 return false;
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800277
278stop:
279 LogTimeEntry::unlock();
280 return -1;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800281}
TraianX Schiauda6495d2014-12-17 10:53:41 +0200282
283void LogTimeEntry::cleanSkip_Locked(void) {
Mark Salyzyn501c3732017-03-10 14:31:54 -0800284 for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t)(i + 1)) {
TraianX Schiauda6495d2014-12-17 10:53:41 +0200285 skipAhead[i] = 0;
286 }
287}