fn shutdown_tasks(&mut self, remaining: Vec<TaskFuture>) {
        // Send a stop request to remaining tasks and wait for them to finish.
        self.stop_sender.send(true).ok();

        // Collect names for remaining tasks for reporting purposes.
        // We have to re-collect, becuase `select_all` does not guarantes the order of returned remaining futures.
        let remaining_tasks_names: Vec<_> = remaining.iter().map(|task| task.id()).collect();
        let remaining_tasks_with_timeout: Vec<_> = remaining
            .into_iter()
            .map(|task| async { tokio::time::timeout(TASK_SHUTDOWN_TIMEOUT, task).await })
            .collect();

        let execution_results = self
            .runtime
            .block_on(futures::future::join_all(remaining_tasks_with_timeout));

        // Report the results of the remaining tasks.
        for (name, result) in remaining_tasks_names.into_iter().zip(execution_results) {
            match result {
                Ok(resolved) => {
                    self.handle_task_exit(resolved, name);
                }
                Err(_) => {
                    tracing::error!("Task {name} timed out");
                    self.errors.push(TaskError::TaskShutdownTimedOut(name));
                }
            }
        }
    }
Sends the stop request and waits for the remaining tasks to finish.
core/lib/node_framework/src/service/mod.rs