blob: ad150bdb6f152074238c9f4a0e90a769116ee26e [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 "LogBuffer.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080022#include "LogReader.h"
Mark Salyzyn501c3732017-03-10 14:31:54 -080023#include "LogTimes.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080024
25pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
26
Tom Cherryc9fa42c2020-04-08 10:37:09 -070027LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
Tom Cherry65ab7fe2019-08-21 14:53:06 -070028 unsigned long tail, log_mask_t logMask, pid_t pid, log_time start_time,
Tom Cherry79d54f72020-05-04 11:13:55 -070029 uint64_t start, uint64_t timeout, bool privileged,
30 bool can_read_security_logs)
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 Cherry79d54f72020-05-04 11:13:55 -070041 mNonBlock(nonBlock),
42 privileged_(privileged),
43 can_read_security_logs_(can_read_security_logs) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080044 mTimeout.tv_sec = timeout / NS_PER_SEC;
45 mTimeout.tv_nsec = timeout % NS_PER_SEC;
Mark Salyzynae2abf12017-03-31 10:48:39 -070046 memset(mLastTid, 0, sizeof(mLastTid));
47 pthread_cond_init(&threadTriggeredCondition, nullptr);
Mark Salyzyn77187782015-05-12 15:21:31 -070048 cleanSkip_Locked();
Mark Salyzyna16f7612014-08-07 08:16:52 -070049}
Mark Salyzyn0175b072014-02-26 09:50:16 -080050
Tom Cherry4f227862018-10-08 17:33:50 -070051bool LogTimeEntry::startReader_Locked() {
Mark Salyzyn765f7822014-04-04 12:47:44 -070052 pthread_attr_t attr;
53
Mark Salyzyn765f7822014-04-04 12:47:44 -070054 if (!pthread_attr_init(&attr)) {
55 if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
Mark Salyzyn501c3732017-03-10 14:31:54 -080056 if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart,
57 this)) {
Mark Salyzyn765f7822014-04-04 12:47:44 -070058 pthread_attr_destroy(&attr);
Tom Cherry4f227862018-10-08 17:33:50 -070059 return true;
Mark Salyzyn765f7822014-04-04 12:47:44 -070060 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080061 }
Mark Salyzyn765f7822014-04-04 12:47:44 -070062 pthread_attr_destroy(&attr);
Mark Salyzyn0175b072014-02-26 09:50:16 -080063 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080064
Tom Cherry4f227862018-10-08 17:33:50 -070065 return false;
Mark Salyzyn0175b072014-02-26 09:50:16 -080066}
67
Mark Salyzyn501c3732017-03-10 14:31:54 -080068void* LogTimeEntry::threadStart(void* obj) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070069 prctl(PR_SET_NAME, "logd.reader.per");
70
Mark Salyzyn501c3732017-03-10 14:31:54 -080071 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -080072
Mark Salyzyn501c3732017-03-10 14:31:54 -080073 SocketClient* client = me->mClient;
Mark Salyzyn0175b072014-02-26 09:50:16 -080074
Mark Salyzyn501c3732017-03-10 14:31:54 -080075 LogBuffer& logbuf = me->mReader.logbuf();
Mark Salyzyn0175b072014-02-26 09:50:16 -080076
Mark Salyzyn047cc072015-06-04 13:35:30 -070077 me->leadingDropped = true;
78
Mark Salyzyn3c501b52017-04-18 14:09:45 -070079 wrlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -080080
Tom Cherry10d086e2019-08-21 14:16:34 -070081 uint64_t start = me->mStart;
Mark Salyzyn0175b072014-02-26 09:50:16 -080082
Tom Cherry4f227862018-10-08 17:33:50 -070083 while (!me->mRelease) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080084 if (me->mTimeout.tv_sec || me->mTimeout.tv_nsec) {
Tom Cherryc9fa42c2020-04-08 10:37:09 -070085 if (pthread_cond_clockwait(&me->threadTriggeredCondition, &timesLock, CLOCK_MONOTONIC,
86 &me->mTimeout) == ETIMEDOUT) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080087 me->mTimeout.tv_sec = 0;
88 me->mTimeout.tv_nsec = 0;
89 }
Tom Cherry4f227862018-10-08 17:33:50 -070090 if (me->mRelease) {
Mark Salyzynb75cce02015-11-30 11:35:56 -080091 break;
92 }
93 }
94
Mark Salyzyn0175b072014-02-26 09:50:16 -080095 unlock();
96
97 if (me->mTail) {
Tom Cherry79d54f72020-05-04 11:13:55 -070098 logbuf.flushTo(client, start, nullptr, me->privileged_, me->can_read_security_logs_,
Mark Salyzynae2abf12017-03-31 10:48:39 -070099 FilterFirstPass, me);
Mark Salyzyn047cc072015-06-04 13:35:30 -0700100 me->leadingDropped = true;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800101 }
Tom Cherry79d54f72020-05-04 11:13:55 -0700102 start = logbuf.flushTo(client, start, me->mLastTid, me->privileged_,
103 me->can_read_security_logs_, FilterSecondPass, me);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800104
Tom Cherry65ab7fe2019-08-21 14:53:06 -0700105 // We only ignore entries before the original start time for the first flushTo(), if we
106 // get entries after this first flush before the original start time, then the client
107 // wouldn't have seen them.
108 // Note: this is still racy and may skip out of order events that came in since the last
109 // time the client disconnected and then reconnected with the new start time. The long term
110 // solution here is that clients must request events since a specific sequence number.
111 me->mStartTime.tv_sec = 0;
112 me->mStartTime.tv_nsec = 0;
113
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700114 wrlock();
Mark Salyzyna16f7612014-08-07 08:16:52 -0700115
Mark Salyzyn0175b072014-02-26 09:50:16 -0800116 if (start == LogBufferElement::FLUSH_ERROR) {
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700117 break;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800118 }
119
Tom Cherry10d086e2019-08-21 14:16:34 -0700120 me->mStart = start + 1;
Mark Salyzynde4bb9c2015-09-16 15:34:00 -0700121
Tom Cherry4f227862018-10-08 17:33:50 -0700122 if (me->mNonBlock || me->mRelease) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800123 break;
124 }
125
TraianX Schiauda6495d2014-12-17 10:53:41 +0200126 me->cleanSkip_Locked();
127
Mark Salyzynb75cce02015-11-30 11:35:56 -0800128 if (!me->mTimeout.tv_sec && !me->mTimeout.tv_nsec) {
129 pthread_cond_wait(&me->threadTriggeredCondition, &timesLock);
130 }
Mark Salyzyn0175b072014-02-26 09:50:16 -0800131 }
132
Tom Cherry4f227862018-10-08 17:33:50 -0700133 LogReader& reader = me->mReader;
134 reader.release(client);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800135
Tom Cherry4f227862018-10-08 17:33:50 -0700136 client->decRef();
137
138 LastLogTimes& times = reader.logbuf().mTimes;
139 auto it =
140 std::find_if(times.begin(), times.end(),
141 [&me](const auto& other) { return other.get() == me; });
142
143 if (it != times.end()) {
144 times.erase(it);
145 }
146
147 unlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800148
Mark Salyzynae2abf12017-03-31 10:48:39 -0700149 return nullptr;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800150}
151
152// A first pass to count the number of elements
Mark Salyzyn501c3732017-03-10 14:31:54 -0800153int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
154 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800155
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700156 LogTimeEntry::wrlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800157
Mark Salyzyn047cc072015-06-04 13:35:30 -0700158 if (me->leadingDropped) {
159 if (element->getDropped()) {
160 LogTimeEntry::unlock();
161 return false;
162 }
163 me->leadingDropped = false;
164 }
165
Mark Salyzyn0175b072014-02-26 09:50:16 -0800166 if (me->mCount == 0) {
Tom Cherry10d086e2019-08-21 14:16:34 -0700167 me->mStart = element->getSequence();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800168 }
169
Tom Cherry65ab7fe2019-08-21 14:53:06 -0700170 if ((!me->mPid || me->mPid == element->getPid()) && me->isWatching(element->getLogId()) &&
171 (me->mStartTime == log_time::EPOCH || me->mStartTime <= element->getRealTime())) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800172 ++me->mCount;
173 }
174
175 LogTimeEntry::unlock();
176
177 return false;
178}
179
180// A second pass to send the selected elements
Mark Salyzyn501c3732017-03-10 14:31:54 -0800181int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
182 LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
Mark Salyzyn0175b072014-02-26 09:50:16 -0800183
Mark Salyzyn3c501b52017-04-18 14:09:45 -0700184 LogTimeEntry::wrlock();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800185
Tom Cherry10d086e2019-08-21 14:16:34 -0700186 me->mStart = element->getSequence();
TraianX Schiauda6495d2014-12-17 10:53:41 +0200187
188 if (me->skipAhead[element->getLogId()]) {
189 me->skipAhead[element->getLogId()]--;
Mark Salyzyn8d7656b2014-06-05 15:58:43 -0700190 goto skip;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800191 }
192
Mark Salyzyn047cc072015-06-04 13:35:30 -0700193 if (me->leadingDropped) {
194 if (element->getDropped()) {
195 goto skip;
196 }
197 me->leadingDropped = false;
198 }
199
Mark Salyzyn0175b072014-02-26 09:50:16 -0800200 // Truncate to close race between first and second pass
201 if (me->mNonBlock && me->mTail && (me->mIndex >= me->mCount)) {
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800202 goto stop;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800203 }
204
TraianX Schiauda6495d2014-12-17 10:53:41 +0200205 if (!me->isWatching(element->getLogId())) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800206 goto skip;
207 }
208
209 if (me->mPid && (me->mPid != element->getPid())) {
210 goto skip;
211 }
212
Tom Cherry65ab7fe2019-08-21 14:53:06 -0700213 if (me->mStartTime != log_time::EPOCH && element->getRealTime() <= me->mStartTime) {
214 goto skip;
215 }
216
Jintao_Zhu5f930722018-11-11 03:13:24 -0800217 if (me->mRelease) {
218 goto stop;
219 }
220
Mark Salyzyn0175b072014-02-26 09:50:16 -0800221 if (!me->mTail) {
222 goto ok;
223 }
224
225 ++me->mIndex;
226
227 if ((me->mCount > me->mTail) && (me->mIndex <= (me->mCount - me->mTail))) {
228 goto skip;
229 }
230
231 if (!me->mNonBlock) {
232 me->mTail = 0;
233 }
234
235ok:
TraianX Schiauda6495d2014-12-17 10:53:41 +0200236 if (!me->skipAhead[element->getLogId()]) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800237 LogTimeEntry::unlock();
238 return true;
239 }
Mark Salyzyn501c3732017-03-10 14:31:54 -0800240// FALLTHRU
Mark Salyzyn0175b072014-02-26 09:50:16 -0800241
242skip:
243 LogTimeEntry::unlock();
244 return false;
Mark Salyzynf7c0f752015-03-03 13:39:37 -0800245
246stop:
247 LogTimeEntry::unlock();
248 return -1;
Mark Salyzyn0175b072014-02-26 09:50:16 -0800249}
TraianX Schiauda6495d2014-12-17 10:53:41 +0200250
251void LogTimeEntry::cleanSkip_Locked(void) {
Mark Salyzynae2abf12017-03-31 10:48:39 -0700252 memset(skipAhead, 0, sizeof(skipAhead));
TraianX Schiauda6495d2014-12-17 10:53:41 +0200253}