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"
10 #include <sys/types.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"
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
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
53 bool ReadProcStats(pid_t pid
, std::string
* buffer
) {
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.";
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())
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
<< "'";
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)));
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
]);
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());
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());
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
))
135 std::vector
<std::string
> proc_stats
;
136 if (!ParseProcStats(stats_data
, &proc_stats
))
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
))
146 std::vector
<std::string
> proc_stats
;
147 if (!ParseProcStats(stats_data
, &proc_stats
))
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
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
) {
164 if (proc_stats
.size() > static_cast<size_t>(field_num
))
165 return proc_stats
[field_num
];
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
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
))
184 std::string delimiters
;
185 delimiters
.push_back('\0');
186 Tokenize(cmd_line
, delimiters
, proc_cmd_line_args
);
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
) {
196 for (i
= 0; i
< NAME_MAX
&& d_name
[i
]; ++i
) {
197 if (!IsAsciiDigit(d_name
[i
])) {
204 // Read the process's command line.
206 std::string
pid_string(d_name
);
207 if (!base::StringToInt(pid_string
, &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());
222 DPLOG(ERROR
) << "opendir(" << task_path
.value() << ")";
227 while (struct dirent
* ent
= readdir(dir
)) {
228 pid_t tid
= ProcDirSlotToPid(ent
->d_name
);
232 // Synchronously reading files in /proc is safe.
233 base::ThreadRestrictions::ScopedAllowIO allow_io
;
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
);
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");
254 // Synchronously reading files in /proc is safe.
255 base::ThreadRestrictions::ScopedAllowIO allow_io
;
256 if (!file_util::ReadFileToString(stat_file
, &status
))
260 StringTokenizer
tokenizer(status
, ":\n");
261 ParsingState state
= KEY_NAME
;
262 base::StringPiece last_key_name
;
263 while (tokenizer
.GetNext()) {
266 last_key_name
= tokenizer
.token_piece();
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") {
283 if (!base::StringToSizeT(split_value_str
[0], &value
)) {
301 #if defined(USE_LINUX_BREAKPAD)
302 size_t g_oom_size
= 0U;
305 const char kProcSelfExe
[] = "/proc/self/exe";
307 ProcessId
GetParentProcessId(ProcessHandle process
) {
308 ProcessId pid
= ReadProcStatsAndGetFieldAsInt(process
, VM_PPID
);
314 FilePath
GetProcessExecutablePath(ProcessHandle process
) {
315 FilePath stat_file
= GetProcPidDir(process
).Append("exe");
317 if (!file_util::ReadSymbolicLink(stat_file
, &exe_name
)) {
318 // No such process. Happens frequently in e.g. TerminateAllChromeProcesses
324 ProcessIterator::ProcessIterator(const ProcessFilter
* filter
)
326 procfs_dir_
= opendir(kProcDir
);
329 ProcessIterator::~ProcessIterator() {
331 closedir(procfs_dir_
);
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.
347 const int kSkipLimit
= 200;
348 while (skipped
< kSkipLimit
) {
349 dirent
* slot
= readdir(procfs_dir_
);
350 // all done looking through /proc?
354 // If not a process, keep looking for one.
355 pid
= ProcDirSlotToPid(slot
->d_name
);
361 if (!GetProcCmdline(pid
, &cmd_line_args
))
364 if (!ReadProcStats(pid
, &stats_data
))
366 if (!ParseProcStats(stats_data
, &proc_stats
))
369 std::string runstate
= GetProcStatsFieldAsString(proc_stats
, VM_STATE
);
370 if (runstate
.size() != 1) {
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')
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
) {
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
);
400 bool NamedProcessIterator::IncludeEntry() {
401 if (executable_name_
!= entry().exe_file())
403 return ProcessIterator::IncludeEntry();
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
))
439 *private_bytes
= ws_usage
.priv
* 1024;
442 *shared_bytes
= ws_usage
.shared
* 1024;
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)
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)
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;
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
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
);
499 int retval
= gettimeofday(&now
, NULL
);
502 int64 time
= TimeValToMicroseconds(now
);
504 if (last_time_
== 0) {
505 // First call, just set the last values.
507 last_cpu_
= GetProcessCPU(process_
);
511 int64 time_delta
= time
- last_time_
;
512 DCHECK_NE(time_delta
, 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());
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
))
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()) {
550 last_key_name
= tokenizer
.token_piece();
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
));
575 ProcessMetrics::ProcessMetrics(ProcessHandle process
)
578 last_system_time_(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
))
590 if (proc_stats
.size() <= VM_STIME
)
592 int utime
= GetProcStatsFieldAsInt(proc_stats
, VM_UTIME
);
593 int stime
= GetProcStatsFieldAsInt(proc_stats
, VM_STIME
);
594 return utime
+ stime
;
599 // The format of /proc/meminfo is:
601 // MemTotal: 8235324 kB
602 // MemFree: 1628304 kB
603 // Buffers: 429596 kB
604 // Cached: 4728232 kB
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;
617 SystemMemoryInfoKB::SystemMemoryInfoKB()
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();
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.";
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
);
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");
688 FilePath
geminfo_file("/sys/kernel/debug/dri/0/i915_gem_objects");
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
);
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
);
713 meminfo
->gem_size
+= mali_size
;
715 #endif // defined(ARCH_CPU_ARM_FAMILY)
720 size_t GetSystemCommitCharge() {
721 SystemMemoryInfoKB meminfo
;
722 if (!GetSystemMemoryInfo(&meminfo
))
724 return meminfo
.total
- meminfo
.free
- meminfo
.buffers
- meminfo
.cached
;
729 void OnNoMemorySize(size_t size
) {
730 #if defined(USE_LINUX_BREAKPAD)
735 LOG(FATAL
) << "Out of memory, size = " << size
;
736 LOG(FATAL
) << "Out of memory.";
746 #if !defined(USE_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \
747 !defined(OS_ANDROID) && !defined(THREAD_SANITIZER)
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
);
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
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
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); \
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); \
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
);
826 #endif // !defined(USE_TCMALLOC)
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.";
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.
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
)
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 "
860 int score_len
= static_cast<int>(score_str
.length());
861 return (score_len
== file_util::WriteFile(oom_file
,
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
,