blob: ed8d2f527a726cdc8e714091038c21fd3d94490c [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 Salyzynae2abf12017-03-31 10:48:39 -070018#include <string.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070019#include <sys/prctl.h>
20
Mark Salyzyn0175b072014-02-26 09:50:16 -080021#include "FlushCommand.h"
22#include "LogBuffer.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080023#include "LogReader.h"
Mark Salyzyn501c3732017-03-10 14:31:54 -080024#include "LogTimes.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080025
26pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
27
Tom Cherryc9fa42c2020-04-08 10:37:09 -070028LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
Tom Cherry65ab7fe2019-08-21 14:53:06 -070029 unsigned long tail, log_mask_t logMask, pid_t pid, log_time start_time,
30 uint64_t start, uint64_t timeout)
Tom Cherry4f227862018-10-08 17:33:50 -070031 : leadingDropped(false),
Mark Salyzyn501c3732017-03-10 14:31:54 -080032 mReader(reader),
33 mLogMask(logMask),
34 mPid(pid),
35 mCount(0),
36 mTail(tail),
37 mIndex(0),
38 mClient(client),
Tom Cherry65ab7fe2019-08-21 14:53:06 -070039 mStartTime(start_time),
Mark Salyzyn501c3732017-03-10 14:31:54 -080040 mStart(start),
Tom Cherryc9fa42c2020-04-08 10:37:09 -070041 mNonBlock(nonBlock) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080042 mTimeout.tv_sec = timeout / NS_PER_SEC;
43 mTimeout.tv_nsec = timeout % NS_PER_SEC;
Mark Salyzynae2abf12017-03-31 10:48:39 -070044 memset(mLastTid, 0, sizeof(mLastTid));
45 pthread_cond_init(&threadTriggeredCondition, nullptr);
Mark Salyzyn77187782015-05-12 15:21:31 -070046 cleanSkip_Locked();
Mark Salyzyna16f7612014-08-07 08:16:52 -070047}
Mark Salyzyn0175b072014-02-26 09:50:16 -080048
Tom Cherry4f227862018-10-08 17:33:50 -070049bool LogTimeEntry::startReader_Locked() {
Mark Salyzyn765f7822014-04-04 12:47:44 -070050 pthread_attr_t attr;
51
Mark Salyzyn765f7822014-04-04 12:47:44 -070052 if (!pthread_attr_init(&attr)) {
53 if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080054 if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart,
55 this)) {
Mark Salyzyn765f7822014-04-04 12:47:44 -070056 pthread_attr_destroy(&attr);
Tom Cherry4f227862018-10-08 17:33:50 -070057 return true;
Mark Salyzyn765f7822014-04-04 12:47:44 -070058 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080059 }
Mark Salyzyn765f7822014-04-04 12:47:44 -070060 pthread_attr_destroy(&attr);
Mark Salyzyn0175b072014-02-26 09:50:16 -080061 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080062
Tom Cherry4f227862018-10-08 17:33:50 -070063 return false;
Mark Salyzyn0175b072014-02-26 09:50:16 -080064}
65
Mark Salyzyn501c3732017-03-10 14:31:54 -080066void* LogTimeEntry::threadStart(void* obj) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070067 prctl(PR_SET_NAME, "logd.reader.per");
68
Mark Salyzyn501c3732017-03-10 14:31:54 -080069 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -080070
Mark Salyzyn501c3732017-03-10 14:31:54 -080071 SocketClient* client = me->mClient;
Mark Salyzyn0175b072014-02-26 09:50:16 -080072
Mark Salyzyn501c3732017-03-10 14:31:54 -080073 LogBuffer& logbuf = me->mReader.logbuf();
Mark Salyzyn0175b072014-02-26 09:50:16 -080074
75 bool privileged = FlushCommand::hasReadLogs(client);
Mark Salyzyn8fa88962016-01-26 14:32:35 -080076 bool security = FlushCommand::hasSecurityLogs(client);
Mark Salyzyn0175b072014-02-26 09:50:16 -080077
Mark Salyzyn047cc072015-06-04 13:35:30 -070078 me->leadingDropped = true;
79
Mark Salyzyn3c501b52017-04-18 14:09:45 -070080 wrlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -080081
Tom Cherry10d086e2019-08-21 14:16:34 -070082 uint64_t start = me->mStart;
Mark Salyzyn0175b072014-02-26 09:50:16 -080083
Tom Cherry4f227862018-10-08 17:33:50 -070084 while (!me->mRelease) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080085 if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
Tom Cherryc9fa42c2020-04-08 10:37:09 -070086 if (pthread_cond_clockwait(&me->threadTriggeredCondition, &timesLock, CLOCK_MONOTONIC,
87 &me->mTimeout) == ETIMEDOUT) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080088 me->mTimeout.tv_sec = 0;
89 me->mTimeout.tv_nsec = 0;
90 }
Tom Cherry4f227862018-10-08 17:33:50 -070091 if (me->mRelease) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080092 break;
93 }
94 }
95
Mark Salyzyn0175b072014-02-26 09:50:16 -080096 unlock();
97
98 if (me->mTail) {
Mark Salyzynae2abf12017-03-31 10:48:39 -070099 logbuf.flushTo(client, start, nullptr, privileged, security,
100 FilterFirstPass, me);
Mark Salyzyn047cc072015-06-04 13:35:30 -0700101 me->leadingDropped = true;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800102 }
Mark Salyzynae2abf12017-03-31 10:48:39 -0700103 start = logbuf.flushTo(client, start, me->mLastTid, privileged,
104 security, FilterSecondPass, me);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800105
Tom Cherry65ab7fe2019-08-21 14:53:06 -0700106 // We only ignore entries before the original start time for the first flushTo(), if we
107 // get entries after this first flush before the original start time, then the client
108 // wouldn't have seen them.
109 // Note: this is still racy and may skip out of order events that came in since the last
110 // time the client disconnected and then reconnected with the new start time. The long term
111 // solution here is that clients must request events since a specific sequence number.
112 me->mStartTime.tv_sec = 0;
113 me->mStartTime.tv_nsec = 0;
114
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700115 wrlock();
Mark Salyzyna16f7612014-08-07 08:16:52 -0700116
Mark Salyzyn0175b072014-02-26 09:50:16 -0800117 if (start == LogBufferElement::FLUSH_ERROR) {
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700118 break;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800119 }
120
Tom Cherry10d086e2019-08-21 14:16:34 -0700121 me->mStart = start + 1;
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700122
Tom Cherry4f227862018-10-08 17:33:50 -0700123 if (me->mNonBlock || me->mRelease) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800124 break;
125 }
126
TraianX Schiauda6495d2014-12-17 10:53:41 +0200127 me->cleanSkip_Locked();
128
Mark Salyzynb75cce02015-11-30 11:35:56 -0800129 if (!me->mTimeout.tv_sec && !me->mTimeout.tv_nsec) {
130 pthread_cond_wait(&me->threadTriggeredCondition, &timesLock);
131 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800132 }
133
Tom Cherry4f227862018-10-08 17:33:50 -0700134 LogReader& reader = me->mReader;
135 reader.release(client);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800136
Tom Cherry4f227862018-10-08 17:33:50 -0700137 client->decRef();
138
139 LastLogTimes& times = reader.logbuf().mTimes;
140 auto it =
141 std::find_if(times.begin(), times.end(),
142 [&me](const auto& other) { return other.get() == me; });
143
144 if (it != times.end()) {
145 times.erase(it);
146 }
147
148 unlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800149
Mark Salyzynae2abf12017-03-31 10:48:39 -0700150 return nullptr;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800151}
152
153// A first pass to count the number of elements
Mark Salyzyn501c3732017-03-10 14:31:54 -0800154int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
155 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800156
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700157 LogTimeEntry::wrlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800158
Mark Salyzyn047cc072015-06-04 13:35:30 -0700159 if (me->leadingDropped) {
160 if (element->getDropped()) {
161 LogTimeEntry::unlock();
162 return false;
163 }
164 me->leadingDropped = false;
165 }
166
Mark Salyzyn0175b072014-02-26 09:50:16 -0800167 if (me->mCount == 0) {
Tom Cherry10d086e2019-08-21 14:16:34 -0700168 me->mStart = element->getSequence();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800169 }
170
Tom Cherry65ab7fe2019-08-21 14:53:06 -0700171 if ((!me->mPid || me->mPid == element->getPid()) && me->isWatching(element->getLogId()) &&
172 (me->mStartTime == log_time::EPOCH || me->mStartTime <= element->getRealTime())) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800173 ++me->mCount;
174 }
175
176 LogTimeEntry::unlock();
177
178 return false;
179}
180
181// A second pass to send the selected elements
Mark Salyzyn501c3732017-03-10 14:31:54 -0800182int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
183 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800184
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700185 LogTimeEntry::wrlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800186
Tom Cherry10d086e2019-08-21 14:16:34 -0700187 me->mStart = element->getSequence();
TraianX Schiauda6495d2014-12-17 10:53:41 +0200188
189 if (me->skipAhead[element->getLogId()]) {
190 me->skipAhead[element->getLogId()]--;
Mark Salyzyn8d7656b2014-06-05 15:58:43 -0700191 goto skip;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800192 }
193
Mark Salyzyn047cc072015-06-04 13:35:30 -0700194 if (me->leadingDropped) {
195 if (element->getDropped()) {
196 goto skip;
197 }
198 me->leadingDropped = false;
199 }
200
Mark Salyzyn0175b072014-02-26 09:50:16 -0800201 // Truncate to close race between first and second pass
202 if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800203 goto stop;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800204 }
205
TraianX Schiauda6495d2014-12-17 10:53:41 +0200206 if (!me->isWatching(element->getLogId())) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800207 goto skip;
208 }
209
210 if (me->mPid && (me->mPid != element->getPid())) {
211 goto skip;
212 }
213
Tom Cherry65ab7fe2019-08-21 14:53:06 -0700214 if (me->mStartTime != log_time::EPOCH && element->getRealTime() <= me->mStartTime) {
215 goto skip;
216 }
217
Jintao_Zhu5f930722018-11-11 03:13:24 -0800218 if (me->mRelease) {
219 goto stop;
220 }
221
Mark Salyzyn0175b072014-02-26 09:50:16 -0800222 if (!me->mTail) {
223 goto ok;
224 }
225
226 ++me->mIndex;
227
228 if ((me->mCount > me->mTail) && (me->mIndex <= (me->mCount - me->mTail))) {
229 goto skip;
230 }
231
232 if (!me->mNonBlock) {
233 me->mTail = 0;
234 }
235
236ok:
TraianX Schiauda6495d2014-12-17 10:53:41 +0200237 if (!me->skipAhead[element->getLogId()]) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800238 LogTimeEntry::unlock();
239 return true;
240 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800241// FALLTHRU
Mark Salyzyn0175b072014-02-26 09:50:16 -0800242
243skip:
244 LogTimeEntry::unlock();
245 return false;
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800246
247stop:
248 LogTimeEntry::unlock();
249 return -1;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800250}
TraianX Schiauda6495d2014-12-17 10:53:41 +0200251
252void LogTimeEntry::cleanSkip_Locked(void) {
Mark Salyzynae2abf12017-03-31 10:48:39 -0700253 memset(skipAhead, 0, sizeof(skipAhead));
TraianX Schiauda6495d2014-12-17 10:53:41 +0200254}