Skip to main content

driver_manager_node/
shutdown.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::node::Node;
6use async_trait::async_trait;
7use driver_manager_driver_host::DriverHost;
8use driver_manager_shutdown::{
9    NodeInfo, NodeShutdownBridge, NodeShutdownCoordinator, ShutdownIntent, ShutdownNode,
10};
11use driver_manager_types::{Collection, ShutdownState};
12use log::{debug, error, warn};
13use std::rc::{Rc, Weak};
14
15pub struct NodeBridge(Weak<Node>);
16
17impl NodeBridge {
18    pub fn new(node: Weak<Node>) -> Self {
19        Self(node)
20    }
21}
22
23#[async_trait(?Send)]
24impl ShutdownNode for Node {
25    fn get_shutdown_coordinator(&self) -> std::cell::RefMut<'_, NodeShutdownCoordinator> {
26        self.node_shutdown_coordinator.borrow_mut()
27    }
28    fn name(&self) -> &str {
29        &self.name
30    }
31    async fn finish_shutdown(&self) {
32        if let Some(this) = self.weak_self.upgrade() {
33            this.finish_shutdown().await;
34        }
35    }
36    fn schedule_post_shutdown(&self, intent: ShutdownIntent) {
37        if let Some(this) = self.weak_self.upgrade() {
38            this.schedule_post_shutdown(intent);
39        }
40    }
41    fn set_should_destroy_driver_component(&self, val: bool) {
42        self.set_should_destroy_driver_component(val);
43    }
44}
45
46#[async_trait(?Send)]
47impl NodeShutdownBridge for NodeBridge {
48    fn get_removal_tracker_info(&self, shutdown_state: ShutdownState) -> NodeInfo {
49        if let Some(node) = self.0.upgrade() {
50            NodeInfo {
51                name: node.make_component_moniker(),
52                driver_url: node.driver_url(),
53                collection: node.collection(),
54                state: shutdown_state,
55                host: node.driver_host(),
56            }
57        } else {
58            // Should not happen
59            NodeInfo {
60                name: "".to_string(),
61                driver_url: "".to_string(),
62                collection: Collection::None,
63                state: ShutdownState::Stopped,
64                host: None,
65            }
66        }
67    }
68    fn stop_driver(&self) {
69        if let Some(node) = self.0.upgrade() {
70            node.stop_driver();
71        }
72    }
73    fn stop_driver_component(&self) {
74        if let Some(node) = self.0.upgrade() {
75            node.stop_driver_component();
76        }
77    }
78    fn is_pending_bind(&self) -> bool {
79        if let Some(node) = self.0.upgrade() { node.is_pending_bind() } else { false }
80    }
81    fn has_children(&self) -> bool {
82        if let Some(node) = self.0.upgrade() { !node.children().is_empty() } else { false }
83    }
84    fn has_driver(&self) -> bool {
85        if let Some(node) = self.0.upgrade() { node.has_driver() } else { false }
86    }
87    fn has_driver_component(&self) -> bool {
88        if let Some(node) = self.0.upgrade() { node.has_driver_component() } else { false }
89    }
90    fn has_driver_component_controller(&self) -> bool {
91        if let Some(node) = self.0.upgrade() {
92            node.has_component_controller_proxy()
93        } else {
94            false
95        }
96    }
97    fn maybe_destroy_driver_component(&self, intent: ShutdownIntent) -> bool {
98        if let Some(node) = self.0.upgrade() {
99            node.maybe_destroy_driver_component(intent)
100        } else {
101            false
102        }
103    }
104    fn get_driver_host(&self) -> Option<Rc<dyn DriverHost>> {
105        let node = self.0.upgrade()?;
106        node.driver_host()
107    }
108    fn collection(&self) -> Collection {
109        if let Some(node) = self.0.upgrade() { node.collection() } else { Collection::None }
110    }
111    fn children(&self) -> Vec<Rc<dyn ShutdownNode>> {
112        if let Some(node) = self.0.upgrade() {
113            node.children().into_iter().map(|c| c as Rc<dyn ShutdownNode>).collect()
114        } else {
115            vec![]
116        }
117    }
118    fn get_weak_node(&self) -> Weak<dyn ShutdownNode> {
119        self.0.clone() as Weak<dyn ShutdownNode>
120    }
121}
122
123impl Node {
124    fn remove_child(&self, child: &Rc<Node>) {
125        log::debug!("RemoveChild {} from parent {}", child.name(), self.name());
126        if self.remove_child_from_children(child) {
127            self.node_shutdown_coordinator.borrow_mut().check_node_state();
128        }
129    }
130
131    async fn finish_shutdown(self: &Rc<Self>) {
132        log::debug!("Node: {} finishing shutdown", self.make_component_moniker());
133
134        if let Some(koid) = self.token_koid()
135            && let Some(attributor) = self.node_manager.memory_attributor()
136        {
137            attributor.remove_driver(koid.raw_koid());
138        }
139
140        if let Some(b) = self.take_node_controller() {
141            b.close()
142        }
143
144        self.finish_shutdown_state();
145
146        for parent in self.parents() {
147            if let Some(p) = parent.upgrade() {
148                p.remove_child(self);
149            } else if !self.is_root_node() {
150                warn!("Parent freed before child {} could be removed from it", self.name());
151            }
152        }
153
154        self.reset_node_type();
155    }
156
157    fn schedule_post_shutdown(self: &Rc<Self>, intent: ShutdownIntent) {
158        let self_clone = self.clone();
159        self.scope.spawn_local(async move {
160            self_clone.post_shutdown(intent).await;
161        });
162    }
163
164    async fn post_shutdown(self: &Rc<Self>, intent: ShutdownIntent) {
165        if let Some(koid) = self.token_koid()
166            && let Some(attributor) = self.node_manager.memory_attributor()
167        {
168            attributor.remove_driver(koid.raw_koid());
169        }
170
171        if intent == ShutdownIntent::Restart {
172            log::debug!("Node '{}': finishing restart", self.make_component_moniker());
173            self.finish_restart().await;
174            return;
175        } else if intent == ShutdownIntent::Quarantine {
176            log::debug!("Node '{}': finishing quarantine", self.make_component_moniker());
177            self.finish_quarantine();
178            return;
179        }
180
181        if let Some(cb) = self.take_remove_complete_callback() {
182            let _ = cb.send(());
183        }
184
185        if intent == ShutdownIntent::RebindComposite
186            && let Some(completer) = self.take_composite_rebind_completer()
187        {
188            let _ = completer.send(Ok(()));
189        }
190    }
191
192    async fn finish_restart(self: &Rc<Self>) {
193        self.get_shutdown_coordinator().reset_shutdown();
194        // Store previous url before we reset the state_.
195        let previous_url = self.driver_url();
196
197        // Perform cleanups for previous driver before we try to start the next driver.
198        self.finish_restart_state();
199
200        if self.host_restart_on_crash() {
201            self.take_host();
202        }
203
204        let suffix = self.take_restart_driver_url_suffix();
205        if let Some(suffix) = suffix {
206            let tracker = self.create_bind_result_tracker(false);
207            self.node_manager.bind_to_url(self, &suffix, tracker);
208            return;
209        }
210
211        let package_type = self.driver_package_type();
212        if let Err(e) = self.node_manager.start_driver(self, &previous_url, package_type) {
213            error!("Failed to start driver '{}': {}", self.name(), e);
214        }
215    }
216
217    fn finish_quarantine(self: &Rc<Self>) {
218        self.get_shutdown_coordinator().reset_shutdown();
219        assert!(self.is_quarantined(), "Node::state_ was not set to Quarantined");
220    }
221
222    fn stop_driver(&self) {
223        if self.is_pending_bind() {
224            warn!(
225                "Stopping driver for node '{}' while bind is in process",
226                self.make_component_moniker()
227            );
228            return;
229        }
230
231        if let Some(driver) = self.driver_client_binding()
232            && let Err(e) = driver.stop()
233        {
234            error!("Node: {} failed to stop driver: {}", self.name(), e);
235            self.clear_driver_host();
236        }
237    }
238
239    fn maybe_destroy_driver_component(self: &Rc<Self>, intent: ShutdownIntent) -> bool {
240        if self.should_destroy_driver_component()
241            || intent != ShutdownIntent::Removal
242            || self.has_remove_complete_callback()
243            || self.is_root_node()
244        {
245            let Some(proxy) = self.component_controller_proxy() else {
246                return false;
247            };
248
249            let name = self.make_component_moniker();
250
251            let self_rc = self.clone();
252            self.scope.spawn_local(async move {
253                let e = proxy.destroy().await;
254                match e {
255                    Ok(inner) => match inner {
256                        Ok(()) => (),
257                        Err(e) => {
258                            error!("Node: '{}' destroy failed: {:?}", name, e);
259                        }
260                    },
261                    Err(e) => {
262                        error!("Node: '{}' failed to send destroy: {:?}", name, e);
263                    }
264                }
265
266                self_rc.set_should_destroy_driver_component(false);
267            });
268
269            return true;
270        }
271
272        debug!("Node: '{}' not destroying", self.make_component_moniker());
273        false
274    }
275}