Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(476)

Unified Diff: base/debug/proc_maps_linux.cc

Issue 18661009: Update ReadProcMaps() to reflect lack of atomicity when reading /proc/self/maps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: nits Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/debug/proc_maps_linux.h ('k') | base/debug/proc_maps_linux_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/debug/proc_maps_linux.cc
diff --git a/base/debug/proc_maps_linux.cc b/base/debug/proc_maps_linux.cc
index c9afd45037b7cce2787b5ccc5bdf4d9ed35e3679..b7a5862f7472aceb3c8cece84b4e9578641fe19a 100644
--- a/base/debug/proc_maps_linux.cc
+++ b/base/debug/proc_maps_linux.cc
@@ -4,6 +4,8 @@
#include "base/debug/proc_maps_linux.h"
+#include <fcntl.h>
+
#if defined(OS_LINUX)
#include <inttypes.h>
#endif
@@ -22,9 +24,68 @@
namespace base {
namespace debug {
+// Scans |proc_maps| starting from |pos| returning true if the gate VMA was
+// found, otherwise returns false.
+static bool ContainsGateVMA(std::string* proc_maps, size_t pos) {
+#if defined(ARCH_CPU_ARM_FAMILY)
+ // The gate VMA on ARM kernels is the interrupt vectors page.
+ return proc_maps->find(" [vectors]\n", pos) != std::string::npos;
+#elif defined(ARCH_CPU_X86_64)
+ // The gate VMA on x86 64-bit kernels is the virtual system call page.
+ return proc_maps->find(" [vsyscall]\n", pos) != std::string::npos;
+#else
+ // Otherwise assume there is no gate VMA in which case we shouldn't
+ // get duplicate entires.
+ return false;
+#endif
+}
+
bool ReadProcMaps(std::string* proc_maps) {
- FilePath proc_maps_path("/proc/self/maps");
- return ReadFileToString(proc_maps_path, proc_maps);
+ // seq_file only writes out a page-sized amount on each call. Refer to header
+ // file for details.
+ const long kReadSize = sysconf(_SC_PAGESIZE);
+
+ int fd = HANDLE_EINTR(open("/proc/self/maps", O_RDONLY));
+ if (fd == -1) {
+ DPLOG(ERROR) << "Couldn't open /proc/self/maps";
+ return false;
+ }
+ file_util::ScopedFD fd_closer(&fd);
+ proc_maps->clear();
+
+ while (true) {
+ // To avoid a copy, resize |proc_maps| so read() can write directly into it.
+ // Compute |buffer| afterwards since resize() may reallocate.
+ size_t pos = proc_maps->size();
+ proc_maps->resize(pos + kReadSize);
+ void* buffer = &(*proc_maps)[pos];
+
+ ssize_t bytes_read = HANDLE_EINTR(read(fd, buffer, kReadSize));
+ if (bytes_read < 0) {
+ DPLOG(ERROR) << "Couldn't read /proc/self/maps";
+ proc_maps->clear();
+ return false;
+ }
+
+ // ... and don't forget to trim off excess bytes.
+ proc_maps->resize(pos + bytes_read);
+
+ if (bytes_read == 0)
+ break;
+
+ // The gate VMA is handled as a special case after seq_file has finished
+ // iterating through all entries in the virtual memory table.
+ //
+ // Unfortunately, if additional entries are added at this point in time
+ // seq_file gets confused and the next call to read() will return duplicate
+ // entries including the gate VMA again.
+ //
+ // Avoid this by searching for the gate VMA and breaking early.
+ if (ContainsGateVMA(proc_maps, pos))
+ break;
+ }
+
+ return true;
}
bool ParseProcMaps(const std::string& input,
« no previous file with comments | « base/debug/proc_maps_linux.h ('k') | base/debug/proc_maps_linux_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698