blob: 25c2ad2b76aa4f68b788a537b4ed15dc4ea9bb19 [file] [log] [blame]
Mark Salyzyn12bac902014-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 Salyzyn552b4752015-11-30 11:35:56 -080017#include <errno.h>
Mark Salyzyn486acdb2017-03-31 10:48:39 -070018#include <string.h>
Mark Salyzyn4e5efdc2014-04-28 14:07:23 -070019#include <sys/prctl.h>
20
Mark Salyzynda1b4a12017-03-10 08:44:14 -080021#include <private/android_logger.h>
22
Mark Salyzyn12bac902014-02-26 09:50:16 -080023#include "FlushCommand.h"
24#include "LogBuffer.h"
Mark Salyzyn12bac902014-02-26 09:50:16 -080025#include "LogReader.h"
Mark Salyzynda65bcb2017-03-10 14:31:54 -080026#include "LogTimes.h"
Mark Salyzyn12bac902014-02-26 09:50:16 -080027
28pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
29
Mark Salyzynda65bcb2017-03-10 14:31:54 -080030LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client,
Mark Salyzyn12bac902014-02-26 09:50:16 -080031 bool nonBlock, unsigned long tail,
Mark Salyzynda1b4a12017-03-10 08:44:14 -080032 unsigned int logMask, pid_t pid, log_time start,
Mark Salyzynda65bcb2017-03-10 14:31:54 -080033 uint64_t timeout)
34 : mRefCount(1),
35 mRelease(false),
36 mError(false),
37 threadRunning(false),
38 leadingDropped(false),
39 mReader(reader),
40 mLogMask(logMask),
41 mPid(pid),
42 mCount(0),
43 mTail(tail),
44 mIndex(0),
45 mClient(client),
46 mStart(start),
47 mNonBlock(nonBlock),
Mark Salyzynda1b4a12017-03-10 08:44:14 -080048 mEnd(log_time(android_log_clockid())) {
Mark Salyzyn552b4752015-11-30 11:35:56 -080049 mTimeout.tv_sec = timeout / NS_PER_SEC;
50 mTimeout.tv_nsec = timeout % NS_PER_SEC;
Mark Salyzyn486acdb2017-03-31 10:48:39 -070051 memset(mLastTid, 0, sizeof(mLastTid));
52 pthread_cond_init(&threadTriggeredCondition, nullptr);
Mark Salyzyncd766f92015-05-12 15:21:31 -070053 cleanSkip_Locked();
Mark Salyzyn740d7c22014-08-07 08:16:52 -070054}
Mark Salyzyn12bac902014-02-26 09:50:16 -080055
56void LogTimeEntry::startReader_Locked(void) {
Mark Salyzynca38ae52014-04-04 12:47:44 -070057 pthread_attr_t attr;
58
Mark Salyzyn12bac902014-02-26 09:50:16 -080059 threadRunning = true;
Mark Salyzynca38ae52014-04-04 12:47:44 -070060
61 if (!pthread_attr_init(&attr)) {
62 if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -080063 if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart,
64 this)) {
Mark Salyzynca38ae52014-04-04 12:47:44 -070065 pthread_attr_destroy(&attr);
66 return;
67 }
Mark Salyzyn12bac902014-02-26 09:50:16 -080068 }
Mark Salyzynca38ae52014-04-04 12:47:44 -070069 pthread_attr_destroy(&attr);
Mark Salyzyn12bac902014-02-26 09:50:16 -080070 }
Mark Salyzynca38ae52014-04-04 12:47:44 -070071 threadRunning = false;
72 if (mClient) {
73 mClient->decRef();
74 }
75 decRef_Locked();
Mark Salyzyn12bac902014-02-26 09:50:16 -080076}
77
Mark Salyzynda65bcb2017-03-10 14:31:54 -080078void LogTimeEntry::threadStop(void* obj) {
79 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn12bac902014-02-26 09:50:16 -080080
Mark Salyzynf4912482017-04-18 14:09:45 -070081 wrlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -080082
Mark Salyzyn12bac902014-02-26 09:50:16 -080083 if (me->mNonBlock) {
84 me->error_Locked();
85 }
86
Mark Salyzynda65bcb2017-03-10 14:31:54 -080087 SocketClient* client = me->mClient;
Mark Salyzyn12bac902014-02-26 09:50:16 -080088
89 if (me->isError_Locked()) {
Mark Salyzynda65bcb2017-03-10 14:31:54 -080090 LogReader& reader = me->mReader;
91 LastLogTimes& times = reader.logbuf().mTimes;
Mark Salyzyn12bac902014-02-26 09:50:16 -080092
93 LastLogTimes::iterator it = times.begin();
Mark Salyzynda65bcb2017-03-10 14:31:54 -080094 while (it != times.end()) {
Mark Salyzyn12bac902014-02-26 09:50:16 -080095 if (*it == me) {
96 times.erase(it);
Mark Salyzyn8954cf42016-03-01 14:59:32 -080097 me->release_nodelete_Locked();
Mark Salyzyn12bac902014-02-26 09:50:16 -080098 break;
99 }
100 it++;
101 }
102
Mark Salyzyn486acdb2017-03-31 10:48:39 -0700103 me->mClient = nullptr;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800104 reader.release(client);
105 }
106
107 if (client) {
108 client->decRef();
109 }
110
Mark Salyzyn740d7c22014-08-07 08:16:52 -0700111 me->threadRunning = false;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800112 me->decRef_Locked();
113
114 unlock();
115}
116
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800117void* LogTimeEntry::threadStart(void* obj) {
Mark Salyzyn4e5efdc2014-04-28 14:07:23 -0700118 prctl(PR_SET_NAME, "logd.reader.per");
119
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800120 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800121
122 pthread_cleanup_push(threadStop, obj);
123
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800124 SocketClient* client = me->mClient;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800125 if (!client) {
126 me->error();
Mark Salyzyn486acdb2017-03-31 10:48:39 -0700127 return nullptr;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800128 }
129
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800130 LogBuffer& logbuf = me->mReader.logbuf();
Mark Salyzyn12bac902014-02-26 09:50:16 -0800131
132 bool privileged = FlushCommand::hasReadLogs(client);
Mark Salyzyn924c0b32016-01-26 14:32:35 -0800133 bool security = FlushCommand::hasSecurityLogs(client);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800134
Mark Salyzyn80c1fc62015-06-04 13:35:30 -0700135 me->leadingDropped = true;
136
Mark Salyzynf4912482017-04-18 14:09:45 -0700137 wrlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -0800138
Mark Salyzynda1b4a12017-03-10 08:44:14 -0800139 log_time start = me->mStart;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800140
Mark Salyzyn8f6914c2015-09-16 15:34:00 -0700141 while (me->threadRunning && !me->isError_Locked()) {
Mark Salyzyn552b4752015-11-30 11:35:56 -0800142 if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
143 if (pthread_cond_timedwait(&me->threadTriggeredCondition,
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800144 &timesLock, &me->mTimeout) == ETIMEDOUT) {
Mark Salyzyn552b4752015-11-30 11:35:56 -0800145 me->mTimeout.tv_sec = 0;
146 me->mTimeout.tv_nsec = 0;
147 }
148 if (!me->threadRunning || me->isError_Locked()) {
149 break;
150 }
151 }
152
Mark Salyzyn12bac902014-02-26 09:50:16 -0800153 unlock();
154
155 if (me->mTail) {
Mark Salyzyn486acdb2017-03-31 10:48:39 -0700156 logbuf.flushTo(client, start, nullptr, privileged, security,
157 FilterFirstPass, me);
Mark Salyzyn80c1fc62015-06-04 13:35:30 -0700158 me->leadingDropped = true;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800159 }
Mark Salyzyn486acdb2017-03-31 10:48:39 -0700160 start = logbuf.flushTo(client, start, me->mLastTid, privileged,
161 security, FilterSecondPass, me);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800162
Mark Salyzynf4912482017-04-18 14:09:45 -0700163 wrlock();
Mark Salyzyn740d7c22014-08-07 08:16:52 -0700164
Mark Salyzyn12bac902014-02-26 09:50:16 -0800165 if (start == LogBufferElement::FLUSH_ERROR) {
Mark Salyzyn740d7c22014-08-07 08:16:52 -0700166 me->error_Locked();
Mark Salyzyn8f6914c2015-09-16 15:34:00 -0700167 break;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800168 }
169
Mark Salyzynda1b4a12017-03-10 08:44:14 -0800170 me->mStart = start + log_time(0, 1);
Mark Salyzyn8f6914c2015-09-16 15:34:00 -0700171
Mark Salyzyn740d7c22014-08-07 08:16:52 -0700172 if (me->mNonBlock || !me->threadRunning || me->isError_Locked()) {
Mark Salyzyn12bac902014-02-26 09:50:16 -0800173 break;
174 }
175
TraianX Schiau6ba427e2014-12-17 10:53:41 +0200176 me->cleanSkip_Locked();
177
Mark Salyzyn552b4752015-11-30 11:35:56 -0800178 if (!me->mTimeout.tv_sec && !me->mTimeout.tv_nsec) {
179 pthread_cond_wait(&me->threadTriggeredCondition, &timesLock);
180 }
Mark Salyzyn12bac902014-02-26 09:50:16 -0800181 }
182
183 unlock();
184
Mark Salyzyn12bac902014-02-26 09:50:16 -0800185 pthread_cleanup_pop(true);
186
Mark Salyzyn486acdb2017-03-31 10:48:39 -0700187 return nullptr;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800188}
189
190// A first pass to count the number of elements
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800191int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
192 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800193
Mark Salyzynf4912482017-04-18 14:09:45 -0700194 LogTimeEntry::wrlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -0800195
Mark Salyzyn80c1fc62015-06-04 13:35:30 -0700196 if (me->leadingDropped) {
197 if (element->getDropped()) {
198 LogTimeEntry::unlock();
199 return false;
200 }
201 me->leadingDropped = false;
202 }
203
Mark Salyzyn12bac902014-02-26 09:50:16 -0800204 if (me->mCount == 0) {
Mark Salyzynda1b4a12017-03-10 08:44:14 -0800205 me->mStart = element->getRealTime();
Mark Salyzyn12bac902014-02-26 09:50:16 -0800206 }
207
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800208 if ((!me->mPid || (me->mPid == element->getPid())) &&
209 (me->isWatching(element->getLogId()))) {
Mark Salyzyn12bac902014-02-26 09:50:16 -0800210 ++me->mCount;
211 }
212
213 LogTimeEntry::unlock();
214
215 return false;
216}
217
218// A second pass to send the selected elements
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800219int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
220 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn12bac902014-02-26 09:50:16 -0800221
Mark Salyzynf4912482017-04-18 14:09:45 -0700222 LogTimeEntry::wrlock();
Mark Salyzyn12bac902014-02-26 09:50:16 -0800223
Mark Salyzynda1b4a12017-03-10 08:44:14 -0800224 me->mStart = element->getRealTime();
TraianX Schiau6ba427e2014-12-17 10:53:41 +0200225
226 if (me->skipAhead[element->getLogId()]) {
227 me->skipAhead[element->getLogId()]--;
Mark Salyzyn0b09a2e2014-06-05 15:58:43 -0700228 goto skip;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800229 }
230
Mark Salyzyn80c1fc62015-06-04 13:35:30 -0700231 if (me->leadingDropped) {
232 if (element->getDropped()) {
233 goto skip;
234 }
235 me->leadingDropped = false;
236 }
237
Mark Salyzyn12bac902014-02-26 09:50:16 -0800238 // Truncate to close race between first and second pass
239 if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
Mark Salyzyn0aaf6cd2015-03-03 13:39:37 -0800240 goto stop;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800241 }
242
TraianX Schiau6ba427e2014-12-17 10:53:41 +0200243 if (!me->isWatching(element->getLogId())) {
Mark Salyzyn12bac902014-02-26 09:50:16 -0800244 goto skip;
245 }
246
247 if (me->mPid && (me->mPid != element->getPid())) {
248 goto skip;
249 }
250
251 if (me->isError_Locked()) {
Mark Salyzyn0aaf6cd2015-03-03 13:39:37 -0800252 goto stop;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800253 }
254
255 if (!me->mTail) {
256 goto ok;
257 }
258
259 ++me->mIndex;
260
261 if ((me->mCount > me->mTail) && (me->mIndex <= (me->mCount - me->mTail))) {
262 goto skip;
263 }
264
265 if (!me->mNonBlock) {
266 me->mTail = 0;
267 }
268
269ok:
TraianX Schiau6ba427e2014-12-17 10:53:41 +0200270 if (!me->skipAhead[element->getLogId()]) {
Mark Salyzyn12bac902014-02-26 09:50:16 -0800271 LogTimeEntry::unlock();
272 return true;
273 }
Mark Salyzynda65bcb2017-03-10 14:31:54 -0800274// FALLTHRU
Mark Salyzyn12bac902014-02-26 09:50:16 -0800275
276skip:
277 LogTimeEntry::unlock();
278 return false;
Mark Salyzyn0aaf6cd2015-03-03 13:39:37 -0800279
280stop:
281 LogTimeEntry::unlock();
282 return -1;
Mark Salyzyn12bac902014-02-26 09:50:16 -0800283}
TraianX Schiau6ba427e2014-12-17 10:53:41 +0200284
285void LogTimeEntry::cleanSkip_Locked(void) {
Mark Salyzyn486acdb2017-03-31 10:48:39 -0700286 memset(skipAhead, 0, sizeof(skipAhead));
TraianX Schiau6ba427e2014-12-17 10:53:41 +0200287}