ART: Print maps directly to log
Do not read proc maps into a string before printing them later back
to the log. In low-memory situations this can cause a bad_alloc.
External bug: http://b.android.com/153990
Bug: 19494774
Change-Id: Ie63d8788afe8c9da65b30b2f89c50d3dbb820755
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 85c9340..2123753 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -133,14 +133,14 @@
}
bool ReadFileToString(const std::string& file_name, std::string* result) {
- std::unique_ptr<File> file(new File);
- if (!file->Open(file_name, O_RDONLY)) {
+ File file;
+ if (!file.Open(file_name, O_RDONLY)) {
return false;
}
std::vector<char> buf(8 * KB);
while (true) {
- int64_t n = TEMP_FAILURE_RETRY(read(file->Fd(), &buf[0], buf.size()));
+ int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[0], buf.size()));
if (n == -1) {
return false;
}
@@ -151,6 +151,59 @@
}
}
+bool PrintFileToLog(const std::string& file_name, LogSeverity level) {
+ File file;
+ if (!file.Open(file_name, O_RDONLY)) {
+ return false;
+ }
+
+ constexpr size_t kBufSize = 256; // Small buffer. Avoid stack overflow and stack size warnings.
+ char buf[kBufSize + 1]; // +1 for terminator.
+ size_t filled_to = 0;
+ while (true) {
+ DCHECK_LT(filled_to, kBufSize);
+ int64_t n = TEMP_FAILURE_RETRY(read(file.Fd(), &buf[filled_to], kBufSize - filled_to));
+ if (n <= 0) {
+ // Print the rest of the buffer, if it exists.
+ if (filled_to > 0) {
+ buf[filled_to] = 0;
+ LOG(level) << buf;
+ }
+ return n == 0;
+ }
+ // Scan for '\n'.
+ size_t i = filled_to;
+ bool found_newline = false;
+ for (; i < filled_to + n; ++i) {
+ if (buf[i] == '\n') {
+ // Found a line break, that's something to print now.
+ buf[i] = 0;
+ LOG(level) << buf;
+ // Copy the rest to the front.
+ if (i + 1 < filled_to + n) {
+ memmove(&buf[0], &buf[i + 1], filled_to + n - i - 1);
+ filled_to = filled_to + n - i - 1;
+ } else {
+ filled_to = 0;
+ }
+ found_newline = true;
+ break;
+ }
+ }
+ if (found_newline) {
+ continue;
+ } else {
+ filled_to += n;
+ // Check if we must flush now.
+ if (filled_to == kBufSize) {
+ buf[kBufSize] = 0;
+ LOG(level) << buf;
+ filled_to = 0;
+ }
+ }
+ }
+}
+
std::string GetIsoDate() {
time_t now = time(NULL);
tm tmbuf;