blob: 01aa62749cbe3d365ec473f0b0a6802845221763 [file] [log] [blame]
// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "login_manager/vpd_process_impl.h"
#include <string>
#include <utility>
#include <vector>
#include "metrics/metrics_library.h"
namespace {
constexpr char kVpdUpdateMetric[] = "Enterprise.VpdUpdateStatus";
} // namespace
namespace login_manager {
VpdProcessImpl::VpdProcessImpl(SystemUtils* system_utils)
: system_utils_(system_utils) {
DCHECK(system_utils_);
}
void VpdProcessImpl::RequestJobExit(const std::string& reason) {
if (subprocess_ && subprocess_->GetPid() > 0)
subprocess_->Kill(SIGTERM);
}
void VpdProcessImpl::EnsureJobExit(base::TimeDelta timeout) {
if (subprocess_) {
if (subprocess_->GetPid() < 0)
return;
if (!system_utils_->ProcessGroupIsGone(subprocess_->GetPid(), timeout)) {
subprocess_->KillEverything(SIGABRT);
DLOG(INFO) << "Child process was killed.";
}
}
}
bool VpdProcessImpl::RunInBackground(const KeyValuePairs& updates,
bool ignore_cache,
const CompletionCallback& completion) {
subprocess_.reset(new Subprocess(0 /*root*/, system_utils_));
std::vector<std::string> argv = {"/usr/sbin/update_rw_vpd"};
for (const auto& entry : updates) {
argv.push_back(entry.first);
argv.push_back(entry.second);
}
std::vector<std::string> env;
if (ignore_cache) {
env.push_back("VPD_IGNORE_CACHE=1");
}
if (!subprocess_->ForkAndExec(argv, env)) {
// The caller remains responsible for running |completion|.
return false;
}
// |completion_| will be run when the job exits.
completion_ = completion;
return true;
}
bool VpdProcessImpl::HandleExit(const siginfo_t& info) {
if (!subprocess_ || subprocess_->GetPid() <= 0 ||
subprocess_->GetPid() != info.si_pid) {
return false;
}
MetricsLibrary metrics;
metrics.SendSparseToUMA(kVpdUpdateMetric, info.si_status);
const bool success = (info.si_status == 0);
LOG_IF(ERROR, !success) << "Failed to update VPD, code = " << info.si_status;
// Reset the completion to ensure we won't call it again.
if (!completion_.is_null())
std::move(completion_).Run(success);
return true;
}
} // namespace login_manager