Allow resize-to-client to be enabled by the user.
[chromium-blink-merge.git] / base / process_util_linux.cc
blob11937f0115ca8412f5cf0be79a826a4fbbfeff68
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/process_util.h"
7 #include <dirent.h>
8 #include <malloc.h>
9 #include <sys/time.h>
10 #include <sys/types.h>
11 #include <unistd.h>
13 #include "base/file_util.h"
14 #include "base/logging.h"
15 #include "base/string_number_conversions.h"
16 #include "base/string_split.h"
17 #include "base/string_tokenizer.h"
18 #include "base/string_util.h"
19 #include "base/sys_info.h"
20 #include "base/threading/thread_restrictions.h"
22 namespace {
24 enum ParsingState {
25 KEY_NAME,
26 KEY_VALUE
29 const char kProcDir[] = "/proc";
30 const char kStatFile[] = "stat";
32 // Returns a FilePath to "/proc/pid".
33 FilePath GetProcPidDir(pid_t pid) {
34 return FilePath(kProcDir).Append(base::IntToString(pid));
37 // Fields from /proc/<pid>/stat, 0-based. See man 5 proc.
38 // If the ordering ever changes, carefully review functions that use these
39 // values.
40 enum ProcStatsFields {
41 VM_COMM = 1, // Filename of executable, without parentheses.
42 VM_STATE = 2, // Letter indicating the state of the process.
43 VM_PPID = 3, // PID of the parent.
44 VM_PGRP = 4, // Process group id.
45 VM_UTIME = 13, // Time scheduled in user mode in clock ticks.
46 VM_STIME = 14, // Time scheduled in kernel mode in clock ticks.
47 VM_VSIZE = 22, // Virtual memory size in bytes.
48 VM_RSS = 23, // Resident Set Size in pages.
51 // Reads /proc/<pid>/stat into |buffer|. Returns true if the file can be read
52 // and is non-empty.
53 bool ReadProcStats(pid_t pid, std::string* buffer) {
54 buffer->clear();
55 // Synchronously reading files in /proc is safe.
56 base::ThreadRestrictions::ScopedAllowIO allow_io;
58 FilePath stat_file = GetProcPidDir(pid).Append(kStatFile);
59 if (!file_util::ReadFileToString(stat_file, buffer)) {
60 DLOG(WARNING) << "Failed to get process stats.";
61 return false;
63 return !buffer->empty();
66 // Takes |stats_data| and populates |proc_stats| with the values split by
67 // spaces. Taking into account the 2nd field may, in itself, contain spaces.
68 // Returns true if successful.
69 bool ParseProcStats(const std::string& stats_data,
70 std::vector<std::string>* proc_stats) {
71 // |stats_data| may be empty if the process disappeared somehow.
72 // e.g. http://crbug.com/145811
73 if (stats_data.empty())
74 return false;
76 // The stat file is formatted as:
77 // pid (process name) data1 data2 .... dataN
78 // Look for the closing paren by scanning backwards, to avoid being fooled by
79 // processes with ')' in the name.
80 size_t open_parens_idx = stats_data.find(" (");
81 size_t close_parens_idx = stats_data.rfind(") ");
82 if (open_parens_idx == std::string::npos ||
83 close_parens_idx == std::string::npos ||
84 open_parens_idx > close_parens_idx) {
85 DLOG(WARNING) << "Failed to find matched parens in '" << stats_data << "'";
86 NOTREACHED();
87 return false;
89 open_parens_idx++;
91 proc_stats->clear();
92 // PID.
93 proc_stats->push_back(stats_data.substr(0, open_parens_idx));
94 // Process name without parentheses.
95 proc_stats->push_back(
96 stats_data.substr(open_parens_idx + 1,
97 close_parens_idx - (open_parens_idx + 1)));
99 // Split the rest.
100 std::vector<std::string> other_stats;
101 base::SplitString(stats_data.substr(close_parens_idx + 2), ' ', &other_stats);
102 for (size_t i = 0; i < other_stats.size(); ++i)
103 proc_stats->push_back(other_stats[i]);
104 return true;
107 // Reads the |field_num|th field from |proc_stats|. Returns 0 on failure.
108 // This version does not handle the first 3 values, since the first value is
109 // simply |pid|, and the next two values are strings.
110 int GetProcStatsFieldAsInt(const std::vector<std::string>& proc_stats,
111 ProcStatsFields field_num) {
112 DCHECK_GE(field_num, VM_PPID);
113 CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
115 int value;
116 return base::StringToInt(proc_stats[field_num], &value) ? value : 0;
119 // Same as GetProcStatsFieldAsInt(), but for size_t values.
120 size_t GetProcStatsFieldAsSizeT(const std::vector<std::string>& proc_stats,
121 ProcStatsFields field_num) {
122 DCHECK_GE(field_num, VM_PPID);
123 CHECK_LT(static_cast<size_t>(field_num), proc_stats.size());
125 size_t value;
126 return base::StringToSizeT(proc_stats[field_num], &value) ? value : 0;
129 // Convenience wrapper around GetProcStatsFieldAsInt(), ParseProcStats() and
130 // ReadProcStats(). See GetProcStatsFieldAsInt() for details.
131 int ReadProcStatsAndGetFieldAsInt(pid_t pid, ProcStatsFields field_num) {
132 std::string stats_data;
133 if (!ReadProcStats(pid, &stats_data))
134 return 0;
135 std::vector<std::string> proc_stats;
136 if (!ParseProcStats(stats_data, &proc_stats))
137 return 0;
138 return GetProcStatsFieldAsInt(proc_stats, field_num);
141 // Same as ReadProcStatsAndGetFieldAsInt() but for size_t values.
142 size_t ReadProcStatsAndGetFieldAsSizeT(pid_t pid, ProcStatsFields field_num) {
143 std::string stats_data;
144 if (!ReadProcStats(pid, &stats_data))
145 return 0;
146 std::vector<std::string> proc_stats;
147 if (!ParseProcStats(stats_data, &proc_stats))
148 return 0;
149 return GetProcStatsFieldAsSizeT(proc_stats, field_num);
152 // Reads the |field_num|th field from |proc_stats|.
153 // Returns an empty string on failure.
154 // This version only handles VM_COMM and VM_STATE, which are the only fields
155 // that are strings.
156 std::string GetProcStatsFieldAsString(
157 const std::vector<std::string>& proc_stats,
158 ProcStatsFields field_num) {
159 if (field_num < VM_COMM || field_num > VM_STATE) {
160 NOTREACHED();
161 return "";
164 if (proc_stats.size() > static_cast<size_t>(field_num))
165 return proc_stats[field_num];
167 NOTREACHED();
168 return 0;
171 // Reads /proc/<pid>/cmdline and populates |proc_cmd_line_args| with the command
172 // line arguments. Returns true if successful.
173 // Note: /proc/<pid>/cmdline contains command line arguments separated by single
174 // null characters. We tokenize it into a vector of strings using '\0' as a
175 // delimiter.
176 bool GetProcCmdline(pid_t pid, std::vector<std::string>* proc_cmd_line_args) {
177 // Synchronously reading files in /proc is safe.
178 base::ThreadRestrictions::ScopedAllowIO allow_io;
180 FilePath cmd_line_file = GetProcPidDir(pid).Append("cmdline");
181 std::string cmd_line;
182 if (!file_util::ReadFileToString(cmd_line_file, &cmd_line))
183 return false;
184 std::string delimiters;
185 delimiters.push_back('\0');
186 Tokenize(cmd_line, delimiters, proc_cmd_line_args);
187 return true;
190 // Take a /proc directory entry named |d_name|, and if it is the directory for
191 // a process, convert it to a pid_t.
192 // Returns 0 on failure.
193 // e.g. /proc/self/ will return 0, whereas /proc/1234 will return 1234.
194 pid_t ProcDirSlotToPid(const char* d_name) {
195 int i;
196 for (i = 0; i < NAME_MAX && d_name[i]; ++i) {
197 if (!IsAsciiDigit(d_name[i])) {
198 return 0;
201 if (i == NAME_MAX)
202 return 0;
204 // Read the process's command line.
205 pid_t pid;
206 std::string pid_string(d_name);
207 if (!base::StringToInt(pid_string, &pid)) {
208 NOTREACHED();
209 return 0;
211 return pid;
214 // Get the total CPU of a single process. Return value is number of jiffies
215 // on success or -1 on error.
216 int GetProcessCPU(pid_t pid) {
217 // Use /proc/<pid>/task to find all threads and parse their /stat file.
218 FilePath task_path = GetProcPidDir(pid).Append("task");
220 DIR* dir = opendir(task_path.value().c_str());
221 if (!dir) {
222 DPLOG(ERROR) << "opendir(" << task_path.value() << ")";
223 return -1;
226 int total_cpu = 0;
227 while (struct dirent* ent = readdir(dir)) {
228 pid_t tid = ProcDirSlotToPid(ent->d_name);
229 if (!tid)
230 continue;
232 // Synchronously reading files in /proc is safe.
233 base::ThreadRestrictions::ScopedAllowIO allow_io;
235 std::string stat;
236 FilePath stat_path = task_path.Append(ent->d_name).Append(kStatFile);
237 if (file_util::ReadFileToString(stat_path, &stat)) {
238 int cpu = base::ParseProcStatCPU(stat);
239 if (cpu > 0)
240 total_cpu += cpu;
243 closedir(dir);
245 return total_cpu;
248 // Read /proc/<pid>/status and returns the value for |field|, or 0 on failure.
249 // Only works for fields in the form of "Field: value kB".
250 size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) {
251 FilePath stat_file = GetProcPidDir(pid).Append("status");
252 std::string status;
254 // Synchronously reading files in /proc is safe.
255 base::ThreadRestrictions::ScopedAllowIO allow_io;
256 if (!file_util::ReadFileToString(stat_file, &status))
257 return 0;
260 StringTokenizer tokenizer(status, ":\n");
261 ParsingState state = KEY_NAME;
262 base::StringPiece last_key_name;
263 while (tokenizer.GetNext()) {
264 switch (state) {
265 case KEY_NAME:
266 last_key_name = tokenizer.token_piece();
267 state = KEY_VALUE;
268 break;
269 case KEY_VALUE:
270 DCHECK(!last_key_name.empty());
271 if (last_key_name == field) {
272 std::string value_str;
273 tokenizer.token_piece().CopyToString(&value_str);
274 std::string value_str_trimmed;
275 TrimWhitespaceASCII(value_str, TRIM_ALL, &value_str_trimmed);
276 std::vector<std::string> split_value_str;
277 base::SplitString(value_str_trimmed, ' ', &split_value_str);
278 if (split_value_str.size() != 2 || split_value_str[1] != "kB") {
279 NOTREACHED();
280 return 0;
282 size_t value;
283 if (!base::StringToSizeT(split_value_str[0], &value)) {
284 NOTREACHED();
285 return 0;
287 return value;
289 state = KEY_NAME;
290 break;
293 NOTREACHED();
294 return 0;
297 } // namespace
299 namespace base {
301 #if defined(USE_LINUX_BREAKPAD)
302 size_t g_oom_size = 0U;
303 #endif
305 const char kProcSelfExe[] = "/proc/self/exe";
307 ProcessId GetParentProcessId(ProcessHandle process) {
308 ProcessId pid = ReadProcStatsAndGetFieldAsInt(process, VM_PPID);
309 if (pid)
310 return pid;
311 return -1;
314 FilePath GetProcessExecutablePath(ProcessHandle process) {
315 FilePath stat_file = GetProcPidDir(process).Append("exe");
316 FilePath exe_name;
317 if (!file_util::ReadSymbolicLink(stat_file, &exe_name)) {
318 // No such process. Happens frequently in e.g. TerminateAllChromeProcesses
319 return FilePath();
321 return exe_name;
324 ProcessIterator::ProcessIterator(const ProcessFilter* filter)
325 : filter_(filter) {
326 procfs_dir_ = opendir(kProcDir);
329 ProcessIterator::~ProcessIterator() {
330 if (procfs_dir_) {
331 closedir(procfs_dir_);
332 procfs_dir_ = NULL;
336 bool ProcessIterator::CheckForNextProcess() {
337 // TODO(port): skip processes owned by different UID
339 pid_t pid = kNullProcessId;
340 std::vector<std::string> cmd_line_args;
341 std::string stats_data;
342 std::vector<std::string> proc_stats;
344 // Arbitrarily guess that there will never be more than 200 non-process
345 // files in /proc. Hardy has 53 and Lucid has 61.
346 int skipped = 0;
347 const int kSkipLimit = 200;
348 while (skipped < kSkipLimit) {
349 dirent* slot = readdir(procfs_dir_);
350 // all done looking through /proc?
351 if (!slot)
352 return false;
354 // If not a process, keep looking for one.
355 pid = ProcDirSlotToPid(slot->d_name);
356 if (!pid) {
357 skipped++;
358 continue;
361 if (!GetProcCmdline(pid, &cmd_line_args))
362 continue;
364 if (!ReadProcStats(pid, &stats_data))
365 continue;
366 if (!ParseProcStats(stats_data, &proc_stats))
367 continue;
369 std::string runstate = GetProcStatsFieldAsString(proc_stats, VM_STATE);
370 if (runstate.size() != 1) {
371 NOTREACHED();
372 continue;
375 // Is the process in 'Zombie' state, i.e. dead but waiting to be reaped?
376 // Allowed values: D R S T Z
377 if (runstate[0] != 'Z')
378 break;
380 // Nope, it's a zombie; somebody isn't cleaning up after their children.
381 // (e.g. WaitForProcessesToExit doesn't clean up after dead children yet.)
382 // There could be a lot of zombies, can't really decrement i here.
384 if (skipped >= kSkipLimit) {
385 NOTREACHED();
386 return false;
389 entry_.pid_ = pid;
390 entry_.ppid_ = GetProcStatsFieldAsInt(proc_stats, VM_PPID);
391 entry_.gid_ = GetProcStatsFieldAsInt(proc_stats, VM_PGRP);
392 entry_.cmd_line_args_.assign(cmd_line_args.begin(), cmd_line_args.end());
394 // TODO(port): read pid's commandline's $0, like killall does. Using the
395 // short name between openparen and closeparen won't work for long names!
396 entry_.exe_file_ = GetProcStatsFieldAsString(proc_stats, VM_COMM);
397 return true;
400 bool NamedProcessIterator::IncludeEntry() {
401 if (executable_name_ != entry().exe_file())
402 return false;
403 return ProcessIterator::IncludeEntry();
407 // static
408 ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
409 return new ProcessMetrics(process);
412 // On linux, we return vsize.
413 size_t ProcessMetrics::GetPagefileUsage() const {
414 return ReadProcStatsAndGetFieldAsSizeT(process_, VM_VSIZE);
417 // On linux, we return the high water mark of vsize.
418 size_t ProcessMetrics::GetPeakPagefileUsage() const {
419 return ReadProcStatusAndGetFieldAsSizeT(process_, "VmPeak") * 1024;
422 // On linux, we return RSS.
423 size_t ProcessMetrics::GetWorkingSetSize() const {
424 return ReadProcStatsAndGetFieldAsSizeT(process_, VM_RSS) * getpagesize();
427 // On linux, we return the high water mark of RSS.
428 size_t ProcessMetrics::GetPeakWorkingSetSize() const {
429 return ReadProcStatusAndGetFieldAsSizeT(process_, "VmHWM") * 1024;
432 bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
433 size_t* shared_bytes) {
434 WorkingSetKBytes ws_usage;
435 if (!GetWorkingSetKBytes(&ws_usage))
436 return false;
438 if (private_bytes)
439 *private_bytes = ws_usage.priv * 1024;
441 if (shared_bytes)
442 *shared_bytes = ws_usage.shared * 1024;
444 return true;
447 // Private and Shared working set sizes are obtained from /proc/<pid>/statm.
448 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
449 // Use statm instead of smaps because smaps is:
450 // a) Large and slow to parse.
451 // b) Unavailable in the SUID sandbox.
453 // First we need to get the page size, since everything is measured in pages.
454 // For details, see: man 5 proc.
455 const int page_size_kb = getpagesize() / 1024;
456 if (page_size_kb <= 0)
457 return false;
459 std::string statm;
461 FilePath statm_file = GetProcPidDir(process_).Append("statm");
462 // Synchronously reading files in /proc is safe.
463 base::ThreadRestrictions::ScopedAllowIO allow_io;
464 bool ret = file_util::ReadFileToString(statm_file, &statm);
465 if (!ret || statm.length() == 0)
466 return false;
469 std::vector<std::string> statm_vec;
470 base::SplitString(statm, ' ', &statm_vec);
471 if (statm_vec.size() != 7)
472 return false; // Not the format we expect.
474 int statm_rss, statm_shared;
475 base::StringToInt(statm_vec[1], &statm_rss);
476 base::StringToInt(statm_vec[2], &statm_shared);
478 ws_usage->priv = (statm_rss - statm_shared) * page_size_kb;
479 ws_usage->shared = statm_shared * page_size_kb;
481 // Sharable is not calculated, as it does not provide interesting data.
482 ws_usage->shareable = 0;
484 return true;
487 double ProcessMetrics::GetCPUUsage() {
488 // This queries the /proc-specific scaling factor which is
489 // conceptually the system hertz. To dump this value on another
490 // system, try
491 // od -t dL /proc/self/auxv
492 // and look for the number after 17 in the output; mine is
493 // 0000040 17 100 3 134512692
494 // which means the answer is 100.
495 // It may be the case that this value is always 100.
496 static const int kHertz = sysconf(_SC_CLK_TCK);
498 struct timeval now;
499 int retval = gettimeofday(&now, NULL);
500 if (retval)
501 return 0;
502 int64 time = TimeValToMicroseconds(now);
504 if (last_time_ == 0) {
505 // First call, just set the last values.
506 last_time_ = time;
507 last_cpu_ = GetProcessCPU(process_);
508 return 0;
511 int64 time_delta = time - last_time_;
512 DCHECK_NE(time_delta, 0);
513 if (time_delta == 0)
514 return 0;
516 int cpu = GetProcessCPU(process_);
518 // We have the number of jiffies in the time period. Convert to percentage.
519 // Note this means we will go *over* 100 in the case where multiple threads
520 // are together adding to more than one CPU's worth.
521 int percentage = 100 * (cpu - last_cpu_) /
522 (kHertz * TimeDelta::FromMicroseconds(time_delta).InSecondsF());
524 last_time_ = time;
525 last_cpu_ = cpu;
527 return percentage;
530 // To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
531 // in your kernel configuration.
532 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
533 // Synchronously reading files in /proc is safe.
534 base::ThreadRestrictions::ScopedAllowIO allow_io;
536 std::string proc_io_contents;
537 FilePath io_file = GetProcPidDir(process_).Append("io");
538 if (!file_util::ReadFileToString(io_file, &proc_io_contents))
539 return false;
541 (*io_counters).OtherOperationCount = 0;
542 (*io_counters).OtherTransferCount = 0;
544 StringTokenizer tokenizer(proc_io_contents, ": \n");
545 ParsingState state = KEY_NAME;
546 StringPiece last_key_name;
547 while (tokenizer.GetNext()) {
548 switch (state) {
549 case KEY_NAME:
550 last_key_name = tokenizer.token_piece();
551 state = KEY_VALUE;
552 break;
553 case KEY_VALUE:
554 DCHECK(!last_key_name.empty());
555 if (last_key_name == "syscr") {
556 base::StringToInt64(tokenizer.token_piece(),
557 reinterpret_cast<int64*>(&(*io_counters).ReadOperationCount));
558 } else if (last_key_name == "syscw") {
559 base::StringToInt64(tokenizer.token_piece(),
560 reinterpret_cast<int64*>(&(*io_counters).WriteOperationCount));
561 } else if (last_key_name == "rchar") {
562 base::StringToInt64(tokenizer.token_piece(),
563 reinterpret_cast<int64*>(&(*io_counters).ReadTransferCount));
564 } else if (last_key_name == "wchar") {
565 base::StringToInt64(tokenizer.token_piece(),
566 reinterpret_cast<int64*>(&(*io_counters).WriteTransferCount));
568 state = KEY_NAME;
569 break;
572 return true;
575 ProcessMetrics::ProcessMetrics(ProcessHandle process)
576 : process_(process),
577 last_time_(0),
578 last_system_time_(0),
579 last_cpu_(0) {
580 processor_count_ = base::SysInfo::NumberOfProcessors();
584 // Exposed for testing.
585 int ParseProcStatCPU(const std::string& input) {
586 std::vector<std::string> proc_stats;
587 if (!ParseProcStats(input, &proc_stats))
588 return -1;
590 if (proc_stats.size() <= VM_STIME)
591 return -1;
592 int utime = GetProcStatsFieldAsInt(proc_stats, VM_UTIME);
593 int stime = GetProcStatsFieldAsInt(proc_stats, VM_STIME);
594 return utime + stime;
597 namespace {
599 // The format of /proc/meminfo is:
601 // MemTotal: 8235324 kB
602 // MemFree: 1628304 kB
603 // Buffers: 429596 kB
604 // Cached: 4728232 kB
605 // ...
606 const size_t kMemTotalIndex = 1;
607 const size_t kMemFreeIndex = 4;
608 const size_t kMemBuffersIndex = 7;
609 const size_t kMemCachedIndex = 10;
610 const size_t kMemActiveAnonIndex = 22;
611 const size_t kMemInactiveAnonIndex = 25;
612 const size_t kMemActiveFileIndex = 28;
613 const size_t kMemInactiveFileIndex = 31;
615 } // namespace
617 SystemMemoryInfoKB::SystemMemoryInfoKB()
618 : total(0),
619 free(0),
620 buffers(0),
621 cached(0),
622 active_anon(0),
623 inactive_anon(0),
624 active_file(0),
625 inactive_file(0),
626 shmem(0),
627 gem_objects(-1),
628 gem_size(-1) {
631 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
632 // Synchronously reading files in /proc is safe.
633 base::ThreadRestrictions::ScopedAllowIO allow_io;
635 // Used memory is: total - free - buffers - caches
636 FilePath meminfo_file("/proc/meminfo");
637 std::string meminfo_data;
638 if (!file_util::ReadFileToString(meminfo_file, &meminfo_data)) {
639 DLOG(WARNING) << "Failed to open " << meminfo_file.value();
640 return false;
642 std::vector<std::string> meminfo_fields;
643 SplitStringAlongWhitespace(meminfo_data, &meminfo_fields);
645 if (meminfo_fields.size() < kMemCachedIndex) {
646 DLOG(WARNING) << "Failed to parse " << meminfo_file.value()
647 << ". Only found " << meminfo_fields.size() << " fields.";
648 return false;
651 DCHECK_EQ(meminfo_fields[kMemTotalIndex-1], "MemTotal:");
652 DCHECK_EQ(meminfo_fields[kMemFreeIndex-1], "MemFree:");
653 DCHECK_EQ(meminfo_fields[kMemBuffersIndex-1], "Buffers:");
654 DCHECK_EQ(meminfo_fields[kMemCachedIndex-1], "Cached:");
655 DCHECK_EQ(meminfo_fields[kMemActiveAnonIndex-1], "Active(anon):");
656 DCHECK_EQ(meminfo_fields[kMemInactiveAnonIndex-1], "Inactive(anon):");
657 DCHECK_EQ(meminfo_fields[kMemActiveFileIndex-1], "Active(file):");
658 DCHECK_EQ(meminfo_fields[kMemInactiveFileIndex-1], "Inactive(file):");
660 base::StringToInt(meminfo_fields[kMemTotalIndex], &meminfo->total);
661 base::StringToInt(meminfo_fields[kMemFreeIndex], &meminfo->free);
662 base::StringToInt(meminfo_fields[kMemBuffersIndex], &meminfo->buffers);
663 base::StringToInt(meminfo_fields[kMemCachedIndex], &meminfo->cached);
664 base::StringToInt(meminfo_fields[kMemActiveAnonIndex], &meminfo->active_anon);
665 base::StringToInt(meminfo_fields[kMemInactiveAnonIndex],
666 &meminfo->inactive_anon);
667 base::StringToInt(meminfo_fields[kMemActiveFileIndex], &meminfo->active_file);
668 base::StringToInt(meminfo_fields[kMemInactiveFileIndex],
669 &meminfo->inactive_file);
670 #if defined(OS_CHROMEOS)
671 // Chrome OS has a tweaked kernel that allows us to query Shmem, which is
672 // usually video memory otherwise invisible to the OS. Unfortunately, the
673 // meminfo format varies on different hardware so we have to search for the
674 // string. It always appears after "Cached:".
675 for (size_t i = kMemCachedIndex+2; i < meminfo_fields.size(); i += 3) {
676 if (meminfo_fields[i] == "Shmem:") {
677 base::StringToInt(meminfo_fields[i+1], &meminfo->shmem);
678 break;
681 #endif
683 // Check for graphics memory data and report if present. Synchronously
684 // reading files in /sys is fast.
685 #if defined(ARCH_CPU_ARM_FAMILY)
686 FilePath geminfo_file("/sys/kernel/debug/dri/0/exynos_gem_objects");
687 #else
688 FilePath geminfo_file("/sys/kernel/debug/dri/0/i915_gem_objects");
689 #endif
690 std::string geminfo_data;
691 meminfo->gem_objects = -1;
692 meminfo->gem_size = -1;
693 if (file_util::ReadFileToString(geminfo_file, &geminfo_data)) {
694 int gem_objects = -1;
695 long long gem_size = -1;
696 int num_res = sscanf(geminfo_data.c_str(),
697 "%d objects, %lld bytes",
698 &gem_objects, &gem_size);
699 if (num_res == 2) {
700 meminfo->gem_objects = gem_objects;
701 meminfo->gem_size = gem_size;
705 #if defined(ARCH_CPU_ARM_FAMILY)
706 // Incorporate Mali graphics memory if present.
707 FilePath mali_memory_file("/sys/devices/platform/mali.0/memory");
708 std::string mali_memory_data;
709 if (file_util::ReadFileToString(mali_memory_file, &mali_memory_data)) {
710 long long mali_size = -1;
711 int num_res = sscanf(mali_memory_data.c_str(), "%lld bytes", &mali_size);
712 if (num_res == 1)
713 meminfo->gem_size += mali_size;
715 #endif // defined(ARCH_CPU_ARM_FAMILY)
717 return true;
720 size_t GetSystemCommitCharge() {
721 SystemMemoryInfoKB meminfo;
722 if (!GetSystemMemoryInfo(&meminfo))
723 return 0;
724 return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached;
727 namespace {
729 void OnNoMemorySize(size_t size) {
730 #if defined(USE_LINUX_BREAKPAD)
731 g_oom_size = size;
732 #endif
734 if (size != 0)
735 LOG(FATAL) << "Out of memory, size = " << size;
736 LOG(FATAL) << "Out of memory.";
739 void OnNoMemory() {
740 OnNoMemorySize(0);
743 } // namespace
745 extern "C" {
746 #if !defined(USE_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \
747 !defined(OS_ANDROID) && !defined(THREAD_SANITIZER)
749 extern "C" {
750 void* __libc_malloc(size_t size);
751 void* __libc_realloc(void* ptr, size_t size);
752 void* __libc_calloc(size_t nmemb, size_t size);
753 void* __libc_valloc(size_t size);
754 void* __libc_pvalloc(size_t size);
755 void* __libc_memalign(size_t alignment, size_t size);
756 } // extern "C"
758 // Overriding the system memory allocation functions:
760 // For security reasons, we want malloc failures to be fatal. Too much code
761 // doesn't check for a NULL return value from malloc and unconditionally uses
762 // the resulting pointer. If the first offset that they try to access is
763 // attacker controlled, then the attacker can direct the code to access any
764 // part of memory.
766 // Thus, we define all the standard malloc functions here and mark them as
767 // visibility 'default'. This means that they replace the malloc functions for
768 // all Chromium code and also for all code in shared libraries. There are tests
769 // for this in process_util_unittest.cc.
771 // If we are using tcmalloc, then the problem is moot since tcmalloc handles
772 // this for us. Thus this code is in a !defined(USE_TCMALLOC) block.
774 // If we are testing the binary with AddressSanitizer, we should not
775 // redefine malloc and let AddressSanitizer do it instead.
777 // We call the real libc functions in this code by using __libc_malloc etc.
778 // Previously we tried using dlsym(RTLD_NEXT, ...) but that failed depending on
779 // the link order. Since ld.so needs calloc during symbol resolution, it
780 // defines its own versions of several of these functions in dl-minimal.c.
781 // Depending on the runtime library order, dlsym ended up giving us those
782 // functions and bad things happened. See crbug.com/31809
784 // This means that any code which calls __libc_* gets the raw libc versions of
785 // these functions.
787 #define DIE_ON_OOM_1(function_name) \
788 void* function_name(size_t) __attribute__ ((visibility("default"))); \
790 void* function_name(size_t size) { \
791 void* ret = __libc_##function_name(size); \
792 if (ret == NULL && size != 0) \
793 OnNoMemorySize(size); \
794 return ret; \
797 #define DIE_ON_OOM_2(function_name, arg1_type) \
798 void* function_name(arg1_type, size_t) \
799 __attribute__ ((visibility("default"))); \
801 void* function_name(arg1_type arg1, size_t size) { \
802 void* ret = __libc_##function_name(arg1, size); \
803 if (ret == NULL && size != 0) \
804 OnNoMemorySize(size); \
805 return ret; \
808 DIE_ON_OOM_1(malloc)
809 DIE_ON_OOM_1(valloc)
810 DIE_ON_OOM_1(pvalloc)
812 DIE_ON_OOM_2(calloc, size_t)
813 DIE_ON_OOM_2(realloc, void*)
814 DIE_ON_OOM_2(memalign, size_t)
816 // posix_memalign has a unique signature and doesn't have a __libc_ variant.
817 int posix_memalign(void** ptr, size_t alignment, size_t size)
818 __attribute__ ((visibility("default")));
820 int posix_memalign(void** ptr, size_t alignment, size_t size) {
821 // This will use the safe version of memalign, above.
822 *ptr = memalign(alignment, size);
823 return 0;
826 #endif // !defined(USE_TCMALLOC)
827 } // extern C
829 void EnableTerminationOnHeapCorruption() {
830 // On Linux, there nothing to do AFAIK.
833 void EnableTerminationOnOutOfMemory() {
834 #if defined(OS_ANDROID)
835 // Android doesn't support setting a new handler.
836 DLOG(WARNING) << "Not feasible.";
837 #else
838 // Set the new-out of memory handler.
839 std::set_new_handler(&OnNoMemory);
840 // If we're using glibc's allocator, the above functions will override
841 // malloc and friends and make them die on out of memory.
842 #endif
845 // NOTE: This is not the only version of this function in the source:
846 // the setuid sandbox (in process_util_linux.c, in the sandbox source)
847 // also has its own C version.
848 bool AdjustOOMScore(ProcessId process, int score) {
849 if (score < 0 || score > kMaxOomScore)
850 return false;
852 FilePath oom_path(GetProcPidDir(process));
854 // Attempt to write the newer oom_score_adj file first.
855 FilePath oom_file = oom_path.AppendASCII("oom_score_adj");
856 if (file_util::PathExists(oom_file)) {
857 std::string score_str = base::IntToString(score);
858 DVLOG(1) << "Adjusting oom_score_adj of " << process << " to "
859 << score_str;
860 int score_len = static_cast<int>(score_str.length());
861 return (score_len == file_util::WriteFile(oom_file,
862 score_str.c_str(),
863 score_len));
866 // If the oom_score_adj file doesn't exist, then we write the old
867 // style file and translate the oom_adj score to the range 0-15.
868 oom_file = oom_path.AppendASCII("oom_adj");
869 if (file_util::PathExists(oom_file)) {
870 // Max score for the old oom_adj range. Used for conversion of new
871 // values to old values.
872 const int kMaxOldOomScore = 15;
874 int converted_score = score * kMaxOldOomScore / kMaxOomScore;
875 std::string score_str = base::IntToString(converted_score);
876 DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
877 int score_len = static_cast<int>(score_str.length());
878 return (score_len == file_util::WriteFile(oom_file,
879 score_str.c_str(),
880 score_len));
883 return false;
886 } // namespace base