liblog: event log tags cache miss call logd for update

Deal with cache miss in the event tag map resources and switch to
"Plan B" to ask long-path to logd for a determination on the tag,
name and format.

logcat-unit-tests liblogcat.descriptive does an under-the-hood call
to logd to add a new logtag but the in-process mapping fails to
pick it up because the /dev/event-tag-map map is SHARED PRIVATE for a
few moments to garner some (linux) efficiency with other copies that
are in the process.  Without the workaround of marking the mapping
dirty to be reread, we are using this change as the proper workaround
that fixes the later parts of this test.

Test: gTest logcat-unit-tests --gtest_filter=liblogcat.descriptive
Bug: 31456426
Bug: 35326290
Change-Id: Ibe54d4df00ed92248e1e644ecebc95f60b222b4d
This commit is contained in:
Mark Salyzyn 2017-02-21 16:25:58 -08:00
parent a9ef4dc7a2
commit 2a0044e4b0
1 changed files with 79 additions and 7 deletions

View File

@ -227,19 +227,30 @@ int EventTagMap::find(MapString&& tag) const {
// successful return, it will be pointing to the last character in the
// tag line (i.e. the character before the start of the next line).
//
// lineNum = 0 removes verbose comments and requires us to cache the
// content rather than make direct raw references since the content
// will disappear after the call. A non-zero lineNum means we own the
// data and it will outlive the call.
//
// Returns 0 on success, nonzero on failure.
static int scanTagLine(EventTagMap* map, char** pData, int lineNum) {
char* cp;
unsigned long val = strtoul(*pData, &cp, 10);
if (cp == *pData) {
fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", lineNum);
if (lineNum) {
fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n",
lineNum);
}
errno = EINVAL;
return -1;
}
uint32_t tagIndex = val;
if (tagIndex != val) {
fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", lineNum);
if (lineNum) {
fprintf(stderr, OUT_TAG ": tag number too large on line %d\n",
lineNum);
}
errno = ERANGE;
return -1;
}
@ -248,7 +259,10 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) {
}
if (*cp == '\n') {
fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", lineNum);
if (lineNum) {
fprintf(stderr, OUT_TAG ": missing tag string on line %d\n",
lineNum);
}
errno = EINVAL;
return -1;
}
@ -259,7 +273,10 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) {
size_t tagLen = cp - tag;
if (!isspace(*cp)) {
fprintf(stderr, OUT_TAG ": invalid tag chars on line %d\n", lineNum);
if (lineNum) {
fprintf(stderr, OUT_TAG ": invalid tag chars on line %d\n",
lineNum);
}
errno = EINVAL;
return -1;
}
@ -293,9 +310,18 @@ static int scanTagLine(EventTagMap* map, char** pData, int lineNum) {
#endif
*pData = cp;
if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair(
MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) {
return 0;
if (lineNum) {
if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair(
MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) {
return 0;
}
} else {
// cache
if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair(
MapString(std::string(tag, tagLen)),
MapString(std::string(fmt, fmtLen)))))) {
return 0;
}
}
errno = EMLINK;
return -1;
@ -455,12 +481,55 @@ LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map) {
if (map) delete map;
}
// Cache miss, go to logd to acquire a public reference.
// Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map?
static const TagFmt* __getEventTag(EventTagMap* map, unsigned int tag) {
// call event tag service to arrange for a new tag
char *buf = NULL;
// Can not use android::base::StringPrintf, asprintf + free instead.
static const char command_template[] = "getEventTag id=%u";
int ret = asprintf(&buf, command_template, tag);
if (ret > 0) {
// Add some buffer margin for an estimate of the full return content.
char *cp;
size_t size = ret - strlen(command_template) +
strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?");
if (size > (size_t)ret) {
cp = static_cast<char*>(realloc(buf, size));
if (cp) {
buf = cp;
} else {
size = ret;
}
} else {
size = ret;
}
// Ask event log tag service for an existing entry
if (__send_log_msg(buf, size) >= 0) {
buf[size - 1] = '\0';
unsigned long val = strtoul(buf, &cp, 10); // return size
if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK
++cp;
if (!scanTagLine(map, &cp, 0)) {
free(buf);
return map->find(tag);
}
}
}
free(buf);
}
return NULL;
}
// Look up an entry in the map.
LIBLOG_ABI_PUBLIC const char* android_lookupEventTag_len(const EventTagMap* map,
size_t *len,
unsigned int tag) {
if (len) *len = 0;
const TagFmt* str = map->find(tag);
if (!str) {
str = __getEventTag(const_cast<EventTagMap*>(map), tag);
}
if (!str) return NULL;
if (len) *len = str->first.length();
return str->first.data();
@ -471,6 +540,9 @@ LIBLOG_ABI_PUBLIC const char* android_lookupEventFormat_len(
const EventTagMap* map, size_t *len, unsigned int tag) {
if (len) *len = 0;
const TagFmt* str = map->find(tag);
if (!str) {
str = __getEventTag(const_cast<EventTagMap*>(map), tag);
}
if (!str) return NULL;
if (len) *len = str->second.length();
return str->second.data();