diff options
author | gspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-23 17:58:21 +0000 |
---|---|---|
committer | gspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-23 17:58:21 +0000 |
commit | 03eb9d27a79f876a039ca30eba54d1155ab5500b (patch) | |
tree | 91c377e970b5e117c09f657a01a172e5bf993709 | |
parent | c25c7be488ea694d9173374b985e73a5a6eed867 (diff) | |
download | chromium_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.cc | 2 | ||||
-rw-r--r-- | base/process_util.h | 39 | ||||
-rw-r--r-- | base/process_util_linux.cc | 43 | ||||
-rw-r--r-- | chrome/app/chrome_main.cc | 47 | ||||
-rw-r--r-- | chrome/browser/oom_priority_manager.cc | 53 | ||||
-rw-r--r-- | chrome/browser/oom_priority_manager.h | 5 | ||||
-rw-r--r-- | chrome/browser/ui/browser_list.h | 2 | ||||
-rw-r--r-- | chrome/common/chrome_constants.cc | 5 | ||||
-rw-r--r-- | chrome/common/chrome_constants.h | 7 | ||||
-rw-r--r-- | content/browser/zygote_host_linux.cc | 37 | ||||
-rw-r--r-- | content/browser/zygote_host_linux.h | 4 | ||||
-rw-r--r-- | sandbox/linux/suid/process_util.h | 13 | ||||
-rw-r--r-- | sandbox/linux/suid/process_util_linux.c | 30 | ||||
-rw-r--r-- | sandbox/linux/suid/sandbox.c | 3 |
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"; |