blob: 6e5c975999f2e7b1bf348d8ba51afe728d6301c0 [file] [log] [blame]
// Copyright 2016 The Fuchsia 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 "src/sys/appmgr/environment_controller_impl.h"
#include <lib/async/default.h>
#include <lib/fit/function.h>
#include <utility>
#include "src/sys/appmgr/realm.h"
namespace component {
EnvironmentControllerImpl::EnvironmentControllerImpl(
fidl::InterfaceRequest<fuchsia::sys::EnvironmentController> request,
std::unique_ptr<Realm> realm)
: binding_(this),
realm_(std::move(realm)),
wait_(this, realm_->job().get(), ZX_TASK_TERMINATED) {
if (request.is_valid()) {
binding_.Bind(std::move(request));
binding_.set_error_handler([this](zx_status_t status) {
ExtractEnvironmentController();
// The destructor of the temporary returned by ExtractChild destroys
// |this| at the end of the previous statement.
});
}
zx_status_t status = wait_.Begin(async_get_default_dispatcher());
FX_DCHECK(status == ZX_OK);
}
// Called when job terminates, regardless of if Kill() was invoked.
void EnvironmentControllerImpl::Handler(async_dispatcher_t* dispatcher, async::WaitBase* wait,
zx_status_t status, const zx_packet_signal* signal) {
FX_DCHECK(status == ZX_OK);
FX_DCHECK((signal->observed & ZX_TASK_TERMINATED) == ZX_TASK_TERMINATED) << signal->observed;
ExtractEnvironmentController();
// The destructor of the temporary returned by ExtractComponent destroys
// |this| at the end of the previous statement.
}
std::unique_ptr<EnvironmentControllerImpl>
EnvironmentControllerImpl::ExtractEnvironmentController() {
if (realm_) {
wait_.Cancel();
auto self = realm_->parent()->ExtractChild(realm_.get());
return self;
}
return nullptr;
}
EnvironmentControllerImpl::~EnvironmentControllerImpl() = default;
void EnvironmentControllerImpl::Kill(KillCallback callback) {
auto self = ExtractEnvironmentController();
if (self) {
realm_->ShutdownNamespace([callback = std::move(callback), self = std::move(self)]() {
callback();
// The |self| destructor destroys |this| when we unwind this stack frame.
});
// kill realm, no need to preserve it
realm_ = nullptr;
callback = nullptr;
} else {
callback();
}
// The |self| destructor destroys |this| when we unwind this stack frame.
}
void EnvironmentControllerImpl::Detach() { binding_.set_error_handler(nullptr); }
void EnvironmentControllerImpl::OnCreated() { binding_.events().OnCreated(); }
} // namespace component