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

Side by Side 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: Created 7 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/proc_maps_linux.h" 5 #include "base/debug/proc_maps_linux.h"
6 6
7 #include <fcntl.h>
8
7 #if defined(OS_LINUX) 9 #if defined(OS_LINUX)
8 #include <inttypes.h> 10 #include <inttypes.h>
9 #endif 11 #endif
10 12
11 #include "base/file_util.h" 13 #include "base/file_util.h"
12 #include "base/strings/string_split.h" 14 #include "base/strings/string_split.h"
13 15
14 #if defined(OS_ANDROID) 16 #if defined(OS_ANDROID)
15 // Bionic's inttypes.h defines PRI/SCNxPTR as an unsigned long int, which 17 // Bionic's inttypes.h defines PRI/SCNxPTR as an unsigned long int, which
16 // is incompatible with Bionic's stdint.h defining uintptr_t as a unsigned int: 18 // is incompatible with Bionic's stdint.h defining uintptr_t as a unsigned int:
17 // https://code.google.com/p/android/issues/detail?id=57218 19 // https://code.google.com/p/android/issues/detail?id=57218
18 #undef SCNxPTR 20 #undef SCNxPTR
19 #define SCNxPTR "x" 21 #define SCNxPTR "x"
20 #endif 22 #endif
21 23
22 namespace base { 24 namespace base {
23 namespace debug { 25 namespace debug {
24 26
27 // Local testing revealed that the size of /proc/<pid>/maps for an official
28 // release build of chrome hovered around the ~45 KB mark with some processes
29 // hitting 80-90 KB.
30 //
31 // We'll play it safe and use 1 MB.
32 enum { kMaxProcMapsSize = 1024 * 1024 };
33
25 bool ReadProcMaps(std::string* proc_maps) { 34 bool ReadProcMaps(std::string* proc_maps) {
26 FilePath proc_maps_path("/proc/self/maps"); 35 scoped_ptr<char[]> buffer(new char[kMaxProcMapsSize]);
27 return file_util::ReadFileToString(proc_maps_path, proc_maps); 36
37 int fd = HANDLE_EINTR(open("/proc/self/maps", O_RDONLY));
38 if (fd == -1) {
39 DPLOG(ERROR) << "Couldn't open /proc/self/maps";
40 return false;
41 }
42 file_util::ScopedFD fd_closer(&fd);
43
44 // XXX there's file_util::ReadFromFD() but it expects an exact # of bytes
45 // to be read whereas here we're reading until EOF. Perhaps we can change
46 // the API / add a new one / add an optional param?
47 ssize_t offset = 0;
48 while (true) {
49 ssize_t bytes_read = HANDLE_EINTR(
50 read(fd, buffer.get() + offset, kMaxProcMapsSize - offset));
Alexander Potapenko 2013/07/11 10:47:23 There must be only one read() call, otherwise we'r
51 if (bytes_read < 0) {
52 DPLOG(ERROR) << "Couldn't read /proc/self/maps";
53 return false;
54 }
55
56 offset += bytes_read;
57 if (offset == kMaxProcMapsSize) {
58 DLOG(ERROR) << "/proc/self/maps is too large";
59 return false;
60 }
61
62 if (bytes_read == 0)
63 break;
64 }
65
66 // Use 2-arg version of assign() to avoid an unnecessary length computation
67 // of |buffer|.
68 buffer[offset] = '\0';
69 proc_maps->assign(buffer.get(), offset);
70 return true;
28 } 71 }
29 72
30 bool ParseProcMaps(const std::string& input, 73 bool ParseProcMaps(const std::string& input,
31 std::vector<MappedMemoryRegion>* regions_out) { 74 std::vector<MappedMemoryRegion>* regions_out) {
32 std::vector<MappedMemoryRegion> regions; 75 std::vector<MappedMemoryRegion> regions;
33 76
34 // This isn't async safe nor terribly efficient, but it doesn't need to be at 77 // This isn't async safe nor terribly efficient, but it doesn't need to be at
35 // this point in time. 78 // this point in time.
36 std::vector<std::string> lines; 79 std::vector<std::string> lines;
37 SplitString(input, '\n', &lines); 80 SplitString(input, '\n', &lines);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 regions.push_back(region); 135 regions.push_back(region);
93 regions.back().path.assign(line + path_index); 136 regions.back().path.assign(line + path_index);
94 } 137 }
95 138
96 regions_out->swap(regions); 139 regions_out->swap(regions);
97 return true; 140 return true;
98 } 141 }
99 142
100 } // namespace debug 143 } // namespace debug
101 } // namespace base 144 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698