| // 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 |