blob: bdd67233616dc62a28e109a5effa8f3cf4589580 [file] [log] [blame]
// Copyright 2020 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 <base/threading/sequenced_task_runner_handle.h>
#include <sys/wait.h>
#include <utility>
#include "vm_tools/concierge/grpc_future_util.h"
#include "vm_tools/concierge/sigchld_handler.h"
namespace vm_tools {
namespace concierge {
Future<bool> SigchldHandler::GetFutureForProc(pid_t pid,
base::TimeDelta timeout) {
DCHECK(sequence_checker_.CalledOnValidSequence());
pid_t ret = waitpid(pid, nullptr, WNOHANG);
if (ret == pid || (ret < 0 && errno == ECHILD)) {
// Either the child exited or it doesn't exist anymore.
return ResolvedFuture(true);
}
Promise<bool> p;
Future<bool> f = p.GetFuture(base::SequencedTaskRunnerHandle::Get());
promise_map_[pid] = std::move(p);
base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(
[](std::weak_ptr<SigchldHandler> weak_handler, pid_t pid) {
std::shared_ptr<SigchldHandler> handler = weak_handler.lock();
if (!handler) {
LOG(WARNING) << "SigchldHandler has already been destroyed.";
return;
}
handler->Timeout(pid);
},
weak_from_this(), pid),
timeout);
return f;
}
bool SigchldHandler::HandlerHelper(pid_t pid, bool result, const char* msg) {
DCHECK(sequence_checker_.CalledOnValidSequence());
auto promiseIter = promise_map_.find(pid);
if (promiseIter != promise_map_.end()) {
LOG(INFO) << msg << pid;
promiseIter->second.SetValue(result);
promise_map_.erase(promiseIter);
return true;
}
return false;
// Should we cancel the delayed task?
}
} // namespace concierge
} // namespace vm_tools