Nice automatic updates up to a point, then renice if necessary.
BUG=5488
TEST=unit tests, gmerged on device and completed an update
successfully with two 100% CPU "nice -n -20" processes
running in the background.
Review URL: http://codereview.chromium.org/3053049
diff --git a/update_attempter.cc b/update_attempter.cc
index 50c59ab..a099d7c 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -114,6 +114,28 @@
return code;
}
+UpdateAttempter::UpdateAttempter(PrefsInterface* prefs,
+ MetricsLibraryInterface* metrics_lib)
+ : dbus_service_(NULL),
+ prefs_(prefs),
+ metrics_lib_(metrics_lib),
+ priority_(utils::kProcessPriorityNormal),
+ manage_priority_source_(NULL),
+ status_(UPDATE_STATUS_IDLE),
+ download_progress_(0.0),
+ last_checked_time_(0),
+ new_version_("0.0.0.0"),
+ new_size_(0) {
+ last_notify_time_.tv_sec = 0;
+ last_notify_time_.tv_nsec = 0;
+ if (utils::FileExists(kUpdateCompletedMarker))
+ status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT;
+}
+
+UpdateAttempter::~UpdateAttempter() {
+ CleanupPriorityManagement();
+}
+
void UpdateAttempter::Update(const std::string& app_version,
const std::string& omaha_url) {
if (status_ == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
@@ -242,6 +264,9 @@
LOG(INFO) << "Processing Done.";
actions_.clear();
+ // Reset process priority back to normal.
+ CleanupPriorityManagement();
+
if (status_ == UPDATE_STATUS_REPORTING_ERROR_EVENT) {
LOG(INFO) << "Error event sent.";
SetStatusAndNotify(UPDATE_STATUS_IDLE);
@@ -269,6 +294,8 @@
}
void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) {
+ // Reset process priority back to normal.
+ CleanupPriorityManagement();
download_progress_ = 0.0;
SetStatusAndNotify(UPDATE_STATUS_IDLE);
actions_.clear();
@@ -301,6 +328,7 @@
// TODO(adlr): put version in InstallPlan
new_version_ = "0.0.0.0";
new_size_ = plan.size;
+ SetupPriorityManagement();
} else if (type == DownloadAction::StaticType()) {
SetStatusAndNotify(UPDATE_STATUS_FINALIZING);
}
@@ -404,4 +432,54 @@
return true;
}
+void UpdateAttempter::SetPriority(utils::ProcessPriority priority) {
+ if (priority_ == priority) {
+ return;
+ }
+ if (utils::SetProcessPriority(priority)) {
+ priority_ = priority;
+ LOG(INFO) << "Process priority = " << priority_;
+ }
+}
+
+void UpdateAttempter::SetupPriorityManagement() {
+ if (manage_priority_source_) {
+ LOG(ERROR) << "Process priority timeout source hasn't been destroyed.";
+ CleanupPriorityManagement();
+ }
+ const int kPriorityTimeout = 10 * 60; // 10 minutes
+ manage_priority_source_ = g_timeout_source_new_seconds(kPriorityTimeout);
+ g_source_set_callback(manage_priority_source_,
+ StaticManagePriorityCallback,
+ this,
+ NULL);
+ g_source_attach(manage_priority_source_, NULL);
+ SetPriority(utils::kProcessPriorityLow);
+}
+
+void UpdateAttempter::CleanupPriorityManagement() {
+ if (manage_priority_source_) {
+ g_source_destroy(manage_priority_source_);
+ manage_priority_source_ = NULL;
+ }
+ SetPriority(utils::kProcessPriorityNormal);
+}
+
+gboolean UpdateAttempter::StaticManagePriorityCallback(gpointer data) {
+ return reinterpret_cast<UpdateAttempter*>(data)->ManagePriorityCallback();
+}
+
+bool UpdateAttempter::ManagePriorityCallback() {
+ // If the current process priority is below normal, set it to normal
+ // and let GLib invoke this callback again.
+ if (utils::ComparePriorities(priority_, utils::kProcessPriorityNormal) < 0) {
+ SetPriority(utils::kProcessPriorityNormal);
+ return true;
+ }
+ // Set the priority to high and let GLib destroy the timeout source.
+ SetPriority(utils::kProcessPriorityHigh);
+ manage_priority_source_ = NULL;
+ return false;
+}
+
} // namespace chromeos_update_engine