summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 17:58:21 +0000
committergspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 17:58:21 +0000
commit03eb9d27a79f876a039ca30eba54d1155ab5500b (patch)
tree91c377e970b5e117c09f657a01a172e5bf993709
parentc25c7be488ea694d9173374b985e73a5a6eed867 (diff)
downloadchromium_src-03eb9d27a79f876a039ca30eba54d1155ab5500b.zip
chromium_src-03eb9d27a79f876a039ca30eba54d1155ab5500b.tar.gz
chromium_src-03eb9d27a79f876a039ca30eba54d1155ab5500b.tar.bz2
Trying again to land OOM priority manager changes.
First landing failed because of an obscure problem with building linux_shared. This change passes the linux_shared trybot (and linux and linux_chromeos trybots). Changing OOM range to 0, 1000 and tweaking OOM algorithm. With this change, we now use the newer oom_score_adj file (with fallback to oom_adj when on a system that doesn't support it) so that we can take advantage of a finer range ([0, 1000] instead of [0, 15]). Also tweaked the OOM priority manager to prioritize things in a slightly different order, preferring (even more) not to kill tabs that the user has currently selected. Original review: http://codereview.chromium.org/7671033/ BUG=chromium-os:18421, chromium:65009 TEST=Ran on device, observed OOM adj values, forced OOM conditions to watch kills. Review URL: http://codereview.chromium.org/7708020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97888 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/process_util.cc2
-rw-r--r--base/process_util.h39
-rw-r--r--base/process_util_linux.cc43
-rw-r--r--chrome/app/chrome_main.cc47
-rw-r--r--chrome/browser/oom_priority_manager.cc53
-rw-r--r--chrome/browser/oom_priority_manager.h5
-rw-r--r--chrome/browser/ui/browser_list.h2
-rw-r--r--chrome/common/chrome_constants.cc5
-rw-r--r--chrome/common/chrome_constants.h7
-rw-r--r--content/browser/zygote_host_linux.cc37
-rw-r--r--content/browser/zygote_host_linux.h4
-rw-r--r--sandbox/linux/suid/process_util.h13
-rw-r--r--sandbox/linux/suid/process_util_linux.c30
-rw-r--r--sandbox/linux/suid/sandbox.c3
14 files changed, 195 insertions, 95 deletions
diff --git a/base/process_util.cc b/base/process_util.cc
index 18e3be7..7fe1a85 100644
--- a/base/process_util.cc
+++ b/base/process_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
diff --git a/base/process_util.h b/base/process_util.h
index b98e266..2109401 100644
--- a/base/process_util.h
+++ b/base/process_util.h
@@ -173,13 +173,18 @@ BASE_EXPORT FilePath GetProcessExecutablePath(ProcessHandle process);
// Exposed for testing.
BASE_EXPORT int ParseProcStatCPU(const std::string& input);
-static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
-
-// This adjusts /proc/process/oom_adj so the Linux OOM killer will prefer
-// certain process types over others. The range for the adjustment is
-// [-17,15], with [0,15] being user accessible.
+// The maximum allowed value for the OOM score.
+const int kMaxOomScore = 1000;
+
+// This adjusts /proc/<pid>/oom_score_adj so the Linux OOM killer will
+// prefer to kill certain process types over others. The range for the
+// adjustment is [-1000, 1000], with [0, 1000] being user accessible.
+// If the Linux system doesn't support the newer oom_score_adj range
+// of [0, 1000], then we revert to using the older oom_adj, and
+// translate the given value into [0, 15]. Some aliasing of values
+// may occur in that case, of course.
BASE_EXPORT bool AdjustOOMScore(ProcessId process, int score);
-#endif
+#endif // defined(OS_LINUX)
#if defined(OS_POSIX)
// Returns the ID for the parent of the given process.
@@ -189,7 +194,7 @@ BASE_EXPORT ProcessId GetParentProcessId(ProcessHandle process);
// given multimap. Only call this function in a child process where you know
// that there aren't any other threads.
BASE_EXPORT void CloseSuperfluousFds(const InjectiveMultimap& saved_map);
-#endif
+#endif // defined(OS_POSIX)
// TODO(evan): rename these to use StudlyCaps.
typedef std::vector<std::pair<std::string, std::string> > environment_vector;
@@ -205,7 +210,7 @@ struct LaunchOptions {
#else
environ(NULL), fds_to_remap(NULL), new_process_group(false),
clone_flags(0)
-#endif
+#endif // !defined(OS_WIN)
{}
// If true, wait for the process to complete.
@@ -248,7 +253,7 @@ struct LaunchOptions {
// If non-zero, start the process using clone(), using flags as provided.
int clone_flags;
-#endif
+#endif // !defined(OS_WIN)
};
// Launch a process via the command line |cmdline|.
@@ -335,7 +340,7 @@ BASE_EXPORT bool GetAppOutputRestricted(const CommandLine& cl,
// |*exit_code|.
BASE_EXPORT bool GetAppOutputWithExitCode(const CommandLine& cl,
std::string* output, int* exit_code);
-#endif
+#endif // defined(OS_POSIX)
// Used to filter processes by process ID.
class ProcessFilter {
@@ -372,12 +377,12 @@ BASE_EXPORT bool KillProcess(ProcessHandle process, int exit_code, bool wait);
// Attempts to kill the process group identified by |process_group_id|. Returns
// true on success.
BASE_EXPORT bool KillProcessGroup(ProcessHandle process_group_id);
-#endif
+#endif // defined(OS_POSIX)
#if defined(OS_WIN)
BASE_EXPORT bool KillProcessById(ProcessId process_id, int exit_code,
bool wait);
-#endif
+#endif // defined(OS_WIN)
// Get the termination status of the process by interpreting the
// circumstances of the child process' death. |exit_code| is set to
@@ -632,7 +637,7 @@ class BASE_EXPORT ProcessMetrics {
explicit ProcessMetrics(ProcessHandle process);
#else
ProcessMetrics(ProcessHandle process, PortProvider* port_provider);
-#endif // !defined(OS_MACOSX)
+#endif // defined(OS_MACOSX)
ProcessHandle process_;
@@ -651,7 +656,7 @@ class BASE_EXPORT ProcessMetrics {
#elif defined(OS_POSIX)
// Jiffie count at the last_time_ we updated.
int last_cpu_;
-#endif // defined(OS_MACOSX)
+#endif // defined(OS_POSIX)
DISALLOW_COPY_AND_ASSIGN(ProcessMetrics);
};
@@ -674,7 +679,7 @@ struct SystemMemoryInfoKB {
// Fills in the provided |meminfo| structure. Returns true on success.
// Exposed for memory debugging widget.
BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
-#endif
+#endif // defined(OS_LINUX)
// Returns the memory committed by the system in KBytes.
// Returns 0 if it can't compute the commit charge.
@@ -699,8 +704,8 @@ BASE_EXPORT void EnableTerminationOnOutOfMemory();
#if defined(OS_MACOSX)
// Exposed for testing.
BASE_EXPORT malloc_zone_t* GetPurgeableZone();
-#endif
-#endif
+#endif // defined(OS_MACOSX)
+#endif // !defined(OS_WIN)
// Enables stack dump to console output on exception and signals.
// When enabled, the process will quit immediately. This is meant to be used in
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
index b350517..f9d151b 100644
--- a/base/process_util_linux.cc
+++ b/base/process_util_linux.cc
@@ -27,6 +27,10 @@
namespace {
+// Max score for the old oom_adj range. Used for conversion of new
+// values to old values.
+const int kMaxOldOomScore = 15;
+
enum ParsingState {
KEY_NAME,
KEY_VALUE
@@ -734,20 +738,41 @@ void EnableTerminationOnOutOfMemory() {
#endif
}
+// NOTE: This is not the only version of this function in the source:
+// the setuid sandbox (in process_util_linux.c, in the sandbox source)
+// also has it's own C version.
bool AdjustOOMScore(ProcessId process, int score) {
- if (score < 0 || score > 15)
+ if (score < 0 || score > kMaxOomScore)
return false;
- FilePath oom_adj("/proc");
- oom_adj = oom_adj.Append(base::Int64ToString(process));
- oom_adj = oom_adj.AppendASCII("oom_adj");
+ FilePath oom_path("/proc");
+ oom_path = oom_path.Append(base::Int64ToString(process));
+
+ // Attempt to write the newer oom_score_adj file first.
+ FilePath oom_file = oom_path.AppendASCII("oom_score_adj");
+ if (file_util::PathExists(oom_file)) {
+ std::string score_str = base::IntToString(score);
+ VLOG(1) << "Adjusting oom_score_adj of " << process << " to " << score_str;
+ int score_len = static_cast<int>(score_str.length());
+ return (score_len == file_util::WriteFile(oom_file,
+ score_str.c_str(),
+ score_len));
+ }
- if (!file_util::PathExists(oom_adj))
- return false;
+ // If the oom_score_adj file doesn't exist, then we write the old
+ // style file and translate the oom_adj score to the range 0-15.
+ oom_file = oom_path.AppendASCII("oom_adj");
+ if (file_util::PathExists(oom_file)) {
+ std::string score_str = base::IntToString(
+ score * kMaxOldOomScore / kMaxOomScore);
+ VLOG(1) << "Adjusting oom_adj of " << process << " to " << score_str;
+ int score_len = static_cast<int>(score_str.length());
+ return (score_len == file_util::WriteFile(oom_file,
+ score_str.c_str(),
+ score_len));
+ }
- std::string score_str = base::IntToString(score);
- return (static_cast<int>(score_str.length()) ==
- file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length()));
+ return false;
}
} // namespace base
diff --git a/chrome/app/chrome_main.cc b/chrome/app/chrome_main.cc
index 1979602..a1d635e 100644
--- a/chrome/app/chrome_main.cc
+++ b/chrome/app/chrome_main.cc
@@ -174,22 +174,31 @@ bool HasDeprecatedArguments(const std::wstring& command_line) {
#if defined(OS_LINUX)
static void AdjustLinuxOOMScore(const std::string& process_type) {
- const int kMiscScore = 7;
-#if defined(OS_CHROMEOS)
- // On ChromeOS, we want plugins to die after the renderers. If this
- // works well for ChromeOS, we may do it for Linux as well.
- const int kPluginScore = 4;
-#else
- const int kPluginScore = 10;
-#endif
+ // Browsers and zygotes should still be killable, but killed last.
+ const int kZygoteScore = 0;
+ // The minimum amount to bump a score by. This is large enough that
+ // even if it's translated into the old values, it will still go up
+ // by at least one.
+ const int kScoreBump = 100;
+ // This is the lowest score that renderers and extensions start with
+ // in the OomPriorityManager.
+ const int kRendererScore = chrome::kLowestRendererOomScore;
+ // For "miscellaneous" things, we want them after renderers,
+ // but before plugins.
+ const int kMiscScore = kRendererScore - kScoreBump;
+ // We want plugins to die after the renderers.
+ const int kPluginScore = kMiscScore - kScoreBump;
int score = -1;
+ DCHECK(kMiscScore > 0);
+ DCHECK(kPluginScore > 0);
+
if (process_type == switches::kPluginProcess ||
process_type == switches::kPpapiPluginProcess) {
score = kPluginScore;
} else if (process_type == switches::kPpapiBrokerProcess) {
- // Kill the broker before the plugin.
- score = kPluginScore + 1;
+ // The broker should be killed before the PPAPI plugin.
+ score = kPluginScore + kScoreBump;
} else if (process_type == switches::kUtilityProcess ||
process_type == switches::kWorkerProcess ||
process_type == switches::kGpuProcess ||
@@ -197,19 +206,25 @@ static void AdjustLinuxOOMScore(const std::string& process_type) {
score = kMiscScore;
} else if (process_type == switches::kProfileImportProcess) {
NOTIMPLEMENTED();
+ score = kZygoteScore;
#ifndef DISABLE_NACL
} else if (process_type == switches::kNaClLoaderProcess) {
score = kPluginScore;
#endif
} else if (process_type == switches::kZygoteProcess ||
process_type.empty()) {
- // Pass - browser / zygote process stays at 0.
+ // For zygotes and unlabeled process types, we want to still make
+ // them killable by the OOM killer.
+ score = kZygoteScore;
} else if (process_type == switches::kExtensionProcess ||
process_type == switches::kRendererProcess) {
LOG(WARNING) << "process type '" << process_type << "' "
- << "should go through the zygote.";
- // When debugging, these process types can end up being run directly.
- return;
+ << "should be created through the zygote.";
+ // When debugging, these process types can end up being run
+ // directly, but this isn't the typical path for assigning the OOM
+ // score for them. Still, we want to assign a score that is
+ // somewhat representative for debugging.
+ score = kRendererScore;
} else {
NOTREACHED() << "Unknown process type";
}
@@ -220,7 +235,7 @@ static void AdjustLinuxOOMScore(const std::string& process_type) {
void SetupCRT(const CommandLine& command_line) {
#if defined(OS_WIN)
-#ifdef _CRTDBG_MAP_ALLOC
+#if defined(_CRTDBG_MAP_ALLOC)
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#else
@@ -535,7 +550,7 @@ int RunNamedProcessTypeMain(const std::string& process_type,
#endif
#if !defined(DISABLE_NACL)
{ switches::kNaClLoaderProcess, NaClMain },
-#ifdef _WIN64 // The broker process is used only on Win64.
+#if defined(_WIN64) // The broker process is used only on Win64.
{ switches::kNaClBrokerProcess, NaClBrokerMain },
#endif
#endif // DISABLE_NACL
diff --git a/chrome/browser/oom_priority_manager.cc b/chrome/browser/oom_priority_manager.cc
index 44abf0f..fcd7a91 100644
--- a/chrome/browser/oom_priority_manager.cc
+++ b/chrome/browser/oom_priority_manager.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/chrome_constants.h"
#include "content/browser/browser_thread.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/tab_contents/tab_contents.h"
@@ -29,7 +30,7 @@ using base::ProcessMetrics;
namespace browser {
-// The default interval in seconds after which to adjust the oom_adj
+// The default interval in seconds after which to adjust the oom_score_adj
// value.
#define ADJUSTMENT_INTERVAL_SECONDS 10
@@ -66,7 +67,11 @@ bool OomPriorityManager::CompareRendererStats(RendererStats first,
static const int64 kTimeBucketInterval =
TimeDelta::FromMinutes(BUCKET_INTERVAL_MINUTES).ToInternalValue();
- // Being pinned is most important.
+ // Being currently selected is most important.
+ if (first.is_selected != second.is_selected)
+ return first.is_selected == true;
+
+ // Being pinned is second most important.
if (first.is_pinned != second.is_pinned)
return first.is_pinned == true;
@@ -82,16 +87,17 @@ bool OomPriorityManager::CompareRendererStats(RendererStats first,
}
// Here we collect most of the information we need to sort the
-// existing renderers in priority order, and hand out oom_adj scores
-// based on that sort order.
+// existing renderers in priority order, and hand out oom_score_adj
+// scores based on that sort order.
//
// Things we need to collect on the browser thread (because
// TabStripModel isn't thread safe):
// 1) whether or not a tab is pinned
// 2) last time a tab was selected
+// 3) is the tab currently selected
//
// We also need to collect:
-// 3) size in memory of a tab
+// 4) size in memory of a tab
// But we do that in DoAdjustOomPriorities on the FILE thread so that
// we avoid jank, because it accesses /proc.
void OomPriorityManager::AdjustOomPriorities() {
@@ -109,7 +115,8 @@ void OomPriorityManager::AdjustOomPriorities() {
stats.last_selected = contents->last_selected_time();
stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
stats.is_pinned = model->IsTabPinned(i);
- stats.memory_used = 0; // This gets calculated in DoAdjustOomPriorities.
+ stats.memory_used = 0; // This gets calculated in DoAdjustOomPriorities.
+ stats.is_selected = model->IsTabSelected(i);
renderer_stats.push_back(stats);
}
}
@@ -145,30 +152,32 @@ void OomPriorityManager::DoAdjustOomPriorities(StatsList renderer_stats) {
renderer_stats.sort(OomPriorityManager::CompareRendererStats);
// Now we assign priorities based on the sorted list. We're
- // assigning priorities in the range of 5 to 10. oom_adj takes
- // values from -17 to 15. Negative values are reserved for system
- // processes, and we want to give some room on either side of the
- // range we're using to allow for things that want to be above or
- // below the renderers in priority, so 5 to 10 gives us some
- // variation in priority without taking up the whole range. In the
- // end, however, it's a pretty arbitrary range to use. Higher
- // values are more likely to be killed by the OOM killer. We also
- // remove any duplicate PIDs, leaving the most important of the
- // duplicates.
- const int kMinPriority = 5;
- const int kMaxPriority = 10;
- const int kPriorityRange = kMaxPriority - kMinPriority;
+ // assigning priorities in the range of kLowestRendererOomScore to
+ // kHighestRendererOomScore (defined in chrome_constants.h).
+ // oom_score_adj takes values from -1000 to 1000. Negative values
+ // are reserved for system processes, and we want to give some room
+ // below the range we're using to allow for things that want to be
+ // above the renderers in priority, so the defined range gives us
+ // some variation in priority without taking up the whole range. In
+ // the end, however, it's a pretty arbitrary range to use. Higher
+ // values are more likely to be killed by the OOM killer.
+ //
+ // We also remove any duplicate PIDs, leaving the most important
+ // (least likely to be killed) of the duplicates, so that a
+ // particular renderer process takes on the oom_score_adj of the
+ // least likely tab to be killed.
+ const int kPriorityRange = chrome::kHighestRendererOomScore -
+ chrome::kLowestRendererOomScore;
float priority_increment =
static_cast<float>(kPriorityRange) / renderer_stats.size();
- float priority = kMinPriority;
+ float priority = chrome::kLowestRendererOomScore;
std::set<base::ProcessHandle> already_seen;
for (StatsList::iterator iterator = renderer_stats.begin();
iterator != renderer_stats.end(); ++iterator) {
if (already_seen.find(iterator->renderer_handle) == already_seen.end()) {
already_seen.insert(iterator->renderer_handle);
ZygoteHost::GetInstance()->AdjustRendererOOMScore(
- iterator->renderer_handle,
- static_cast<int>(priority + 0.5f));
+ iterator->renderer_handle, static_cast<int>(priority + 0.5f));
priority += priority_increment;
}
}
diff --git a/chrome/browser/oom_priority_manager.h b/chrome/browser/oom_priority_manager.h
index 55ce733..3090947d 100644
--- a/chrome/browser/oom_priority_manager.h
+++ b/chrome/browser/oom_priority_manager.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -15,7 +15,7 @@ namespace browser {
// The OomPriorityManager periodically checks (see
// ADJUSTMENT_INTERVAL_SECONDS in the source) the status of renderers
// and adjusts the out of memory (OOM) adjustment value (in
-// /proc/<pid>/oom_adj) of the renderers so that they match the
+// /proc/<pid>/oom_score_adj) of the renderers so that they match the
// algorithm embedded here for priority in being killed upon OOM
// conditions.
//
@@ -32,6 +32,7 @@ class OomPriorityManager {
private:
struct RendererStats {
bool is_pinned;
+ bool is_selected;
base::TimeTicks last_selected;
size_t memory_used;
base::ProcessHandle renderer_handle;
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h
index 3b3f061..b926083 100644
--- a/chrome/browser/ui/browser_list.h
+++ b/chrome/browser/ui/browser_list.h
@@ -244,7 +244,7 @@ class TabContentsIterator {
}
// Returns the Browser instance associated with the current TabContents.
- // Valid as long as !Done()
+ // Valid as long as !done()
Browser* browser() const {
if (browser_iterator_ != BrowserList::end())
return *browser_iterator_;
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 42bc248..844ef3b 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -177,6 +177,11 @@ const bool kEnableTouchIcon = true;
const bool kEnableTouchIcon = false;
#endif
+#if defined(OS_LINUX)
+extern const int kLowestRendererOomScore = 300;
+extern const int kHighestRendererOomScore = 1000;
+#endif
+
} // namespace chrome
#undef FPL
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 4e89208..fb05878 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -99,6 +99,13 @@ extern const int kJavascriptMessageExpectedDelay;
// Are touch icons enabled? False by default.
extern const bool kEnableTouchIcon;
+#if defined(OS_LINUX)
+// The highest and lowest assigned OOM score adjustment
+// (oom_score_adj) used by the OomPriority Manager.
+extern const int kLowestRendererOomScore;
+extern const int kHighestRendererOomScore;
+#endif
+
} // namespace chrome
#endif // CHROME_COMMON_CHROME_CONSTANTS_H_
diff --git a/content/browser/zygote_host_linux.cc b/content/browser/zygote_host_linux.cc
index 42ee6da..dc2fc4e 100644
--- a/content/browser/zygote_host_linux.cc
+++ b/content/browser/zygote_host_linux.cc
@@ -272,28 +272,35 @@ pid_t ZygoteHost::ForkRequest(
return base::kNullProcessHandle;
}
- const int kRendererScore = 5;
- AdjustRendererOOMScore(pid, kRendererScore);
+ // This is just a starting score for a renderer or extension (the
+ // only types of processes that will be started this way). It will
+ // get adjusted as time goes on. (This is the same value as
+ // chrome::kLowestRendererOomScore in chrome/chrome_constants.h, but
+ // that's not something we can include here.)
+ const int kLowestRendererOomScore = 300;
+ AdjustRendererOOMScore(pid, kLowestRendererOomScore);
return pid;
}
void ZygoteHost::AdjustRendererOOMScore(base::ProcessHandle pid, int score) {
- // 1) You can't change the oom_adj of a non-dumpable process (EPERM) unless
- // you're root. Because of this, we can't set the oom_adj from the browser
- // process.
+ // 1) You can't change the oom_score_adj of a non-dumpable process
+ // (EPERM) unless you're root. Because of this, we can't set the
+ // oom_adj from the browser process.
//
- // 2) We can't set the oom_adj before entering the sandbox because the
- // zygote is in the sandbox and the zygote is as critical as the browser
- // process. Its oom_adj value shouldn't be changed.
+ // 2) We can't set the oom_score_adj before entering the sandbox
+ // because the zygote is in the sandbox and the zygote is as
+ // critical as the browser process. Its oom_adj value shouldn't
+ // be changed.
//
- // 3) A non-dumpable process can't even change its own oom_adj because it's
- // root owned 0644. The sandboxed processes don't even have /proc, but one
- // could imagine passing in a descriptor from outside.
+ // 3) A non-dumpable process can't even change its own oom_score_adj
+ // because it's root owned 0644. The sandboxed processes don't
+ // even have /proc, but one could imagine passing in a descriptor
+ // from outside.
//
// So, in the normal case, we use the SUID binary to change it for us.
// However, Fedora (and other SELinux systems) don't like us touching other
- // process's oom_adj values
+ // process's oom_score_adj (or oom_adj) values
// (https://bugzilla.redhat.com/show_bug.cgi?id=581256).
//
// The offical way to get the SELinux mode is selinux_getenforcemode, but I
@@ -319,9 +326,13 @@ void ZygoteHost::AdjustRendererOOMScore(base::ProcessHandle pid, int score) {
if (IsHeapProfilerRunning())
return;
#endif
+ // The command line switch used for supplying the OOM adjustment score
+ // to the setuid sandbox.
+ static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
+
std::vector<std::string> adj_oom_score_cmdline;
adj_oom_score_cmdline.push_back(sandbox_binary_);
- adj_oom_score_cmdline.push_back(base::kAdjustOOMScoreSwitch);
+ adj_oom_score_cmdline.push_back(kAdjustOOMScoreSwitch);
adj_oom_score_cmdline.push_back(base::Int64ToString(pid));
adj_oom_score_cmdline.push_back(base::IntToString(score));
diff --git a/content/browser/zygote_host_linux.h b/content/browser/zygote_host_linux.h
index 9098e6d..facabbb 100644
--- a/content/browser/zygote_host_linux.h
+++ b/content/browser/zygote_host_linux.h
@@ -74,7 +74,9 @@ class ZygoteHost {
return 0;
}
- // Adjust the OOM score of the given renderer's PID.
+ // Adjust the OOM score of the given renderer's PID. The allowed
+ // range for the score is [0, 1000], where higher values are more
+ // likely to be killed by the OOM killer.
void AdjustRendererOOMScore(base::ProcessHandle process_handle, int score);
private:
diff --git a/sandbox/linux/suid/process_util.h b/sandbox/linux/suid/process_util.h
index 6bab897..1826555 100644
--- a/sandbox/linux/suid/process_util.h
+++ b/sandbox/linux/suid/process_util.h
@@ -13,11 +13,14 @@
#include "base/base_export.h"
-static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
-
-// This adjusts /proc/process/oom_adj so the Linux OOM killer will prefer
-// certain process types over others. The range for the adjustment is
-// [-17,15], with [0,15] being user accessible.
+// This adjusts /proc/process/oom_score_adj so the Linux OOM killer
+// will prefer certain process types over others. The range for the
+// adjustment is [-1000, 1000], with [0, 1000] being user accessible.
+//
+// If the Linux system isn't new enough to use oom_score_adj, then we
+// try to set the older oom_adj value instead, scaling the score to
+// the required range of [0, 15]. This may result in some aliasing of
+// values, of course.
BASE_EXPORT bool AdjustOOMScore(pid_t process, int score);
#endif // SANDBOX_LINUX_SUID_PROCESS_UTIL_H_
diff --git a/sandbox/linux/suid/process_util_linux.c b/sandbox/linux/suid/process_util_linux.c
index 17453de..13f45ce 100644
--- a/sandbox/linux/suid/process_util_linux.c
+++ b/sandbox/linux/suid/process_util_linux.c
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -19,8 +19,13 @@
#include <sys/types.h>
#include <unistd.h>
+// Ranges for the current (oom_score_adj) and previous (oom_adj)
+// flavors of OOM score.
+static const int kMaxOomScore = 1000;
+static const int kMaxOldOomScore = 15;
+
bool AdjustOOMScore(pid_t process, int score) {
- if (score < 0 || score > 15)
+ if (score < 0 || score > kMaxOomScore)
return false;
char oom_adj[27]; // "/proc/" + log_10(2**64) + "\0"
@@ -41,13 +46,24 @@ bool AdjustOOMScore(pid_t process, int score) {
return false;
}
- const int fd = openat(dirfd, "oom_adj", O_WRONLY);
+ int fd = openat(dirfd, "oom_score_adj", O_WRONLY);
+ if (fd < 0) {
+ // We failed to open oom_score_adj, so let's try for the older
+ // oom_adj file instead.
+ fd = openat(dirfd, "oom_adj", O_WRONLY);
+ if (fd < 0) {
+ // Nope, that doesn't work either.
+ return false;
+ } else {
+ // If we're using the old oom_adj file, the allowed range is now
+ // [0, kMaxOldOomScore], so we scale the score. This may result in some
+ // aliasing of values, of course.
+ score = score * kMaxOldOomScore / kMaxOomScore;
+ }
+ }
close(dirfd);
- if (fd < 0)
- return false;
-
- char buf[3]; // 0 <= |score| <= 15;
+ char buf[11]; // 0 <= |score| <= kMaxOomScore; using log_10(2**32) + 1 size
snprintf(buf, sizeof(buf), "%d", score);
size_t len = strlen(buf);
diff --git a/sandbox/linux/suid/sandbox.c b/sandbox/linux/suid/sandbox.c
index 1cf95284..a545208 100644
--- a/sandbox/linux/suid/sandbox.c
+++ b/sandbox/linux/suid/sandbox.c
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -37,6 +37,7 @@
#define CLONE_NEWNET 0x40000000
#endif
+static const char kAdjustOOMScoreSwitch[] = "--adjust-oom-score";
static const char kSandboxDescriptorEnvironmentVarName[] = "SBX_D";
static const char kSandboxHelperPidEnvironmentVarName[] = "SBX_HELPER_PID";