• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "base/process/memory.h"
6 
7 #include <stddef.h>
8 
9 #include <new>
10 
11 #include "base/allocator/allocator_shim.h"
12 #include "base/allocator/buildflags.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/logging.h"
16 #include "base/process/internal_linux.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "build/build_config.h"
19 
20 #if defined(USE_TCMALLOC)
21 #include "third_party/tcmalloc/gperftools-2.0/chromium/src/config.h"
22 #include "third_party/tcmalloc/gperftools-2.0/chromium/src/gperftools/tcmalloc.h"
23 #endif
24 
25 extern "C" {
26 void* __libc_malloc(size_t size);
27 }
28 
29 namespace base {
30 
31 size_t g_oom_size = 0U;
32 
33 namespace {
34 
OnNoMemorySize(size_t size)35 void OnNoMemorySize(size_t size) {
36   g_oom_size = size;
37 
38   if (size != 0)
39     LOG(FATAL) << "Out of memory, size = " << size;
40   LOG(FATAL) << "Out of memory.";
41 }
42 
OnNoMemory()43 void OnNoMemory() {
44   OnNoMemorySize(0);
45 }
46 
47 }  // namespace
48 
EnableTerminationOnHeapCorruption()49 void EnableTerminationOnHeapCorruption() {
50   // On Linux, there nothing to do AFAIK.
51 }
52 
EnableTerminationOnOutOfMemory()53 void EnableTerminationOnOutOfMemory() {
54   // Set the new-out of memory handler.
55   std::set_new_handler(&OnNoMemory);
56   // If we're using glibc's allocator, the above functions will override
57   // malloc and friends and make them die on out of memory.
58 
59 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
60   allocator::SetCallNewHandlerOnMallocFailure(true);
61 #elif defined(USE_TCMALLOC)
62   // For tcmalloc, we need to tell it to behave like new.
63   tc_set_new_mode(1);
64 #endif
65 }
66 
67 // NOTE: This is not the only version of this function in the source:
68 // the setuid sandbox (in process_util_linux.c, in the sandbox source)
69 // also has its own C version.
AdjustOOMScore(ProcessId process,int score)70 bool AdjustOOMScore(ProcessId process, int score) {
71   if (score < 0 || score > kMaxOomScore)
72     return false;
73 
74   FilePath oom_path(internal::GetProcPidDir(process));
75 
76   // Attempt to write the newer oom_score_adj file first.
77   FilePath oom_file = oom_path.AppendASCII("oom_score_adj");
78   if (PathExists(oom_file)) {
79     std::string score_str = IntToString(score);
80     DVLOG(1) << "Adjusting oom_score_adj of " << process << " to "
81              << score_str;
82     int score_len = static_cast<int>(score_str.length());
83     return (score_len == WriteFile(oom_file, score_str.c_str(), score_len));
84   }
85 
86   // If the oom_score_adj file doesn't exist, then we write the old
87   // style file and translate the oom_adj score to the range 0-15.
88   oom_file = oom_path.AppendASCII("oom_adj");
89   if (PathExists(oom_file)) {
90     // Max score for the old oom_adj range.  Used for conversion of new
91     // values to old values.
92     const int kMaxOldOomScore = 15;
93 
94     int converted_score = score * kMaxOldOomScore / kMaxOomScore;
95     std::string score_str = IntToString(converted_score);
96     DVLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
97     int score_len = static_cast<int>(score_str.length());
98     return (score_len == WriteFile(oom_file, score_str.c_str(), score_len));
99   }
100 
101   return false;
102 }
103 
UncheckedMalloc(size_t size,void ** result)104 bool UncheckedMalloc(size_t size, void** result) {
105 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
106   *result = allocator::UncheckedAlloc(size);
107 #elif defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || \
108     (!defined(LIBC_GLIBC) && !defined(USE_TCMALLOC))
109   *result = malloc(size);
110 #elif defined(LIBC_GLIBC) && !defined(USE_TCMALLOC)
111   *result = __libc_malloc(size);
112 #elif defined(USE_TCMALLOC)
113   *result = tc_malloc_skip_new_handler(size);
114 #endif
115   return *result != nullptr;
116 }
117 
118 }  // namespace base
119