1 // Copyright © 2021 Intel Corporation 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 6 use std::panic::AssertUnwindSafe; 7 use std::thread::{self, JoinHandle}; 8 9 use seccompiler::{apply_filter, SeccompAction}; 10 use vmm_sys_util::eventfd::EventFd; 11 12 use crate::epoll_helper::EpollHelperError; 13 use crate::seccomp_filters::{get_seccomp_filter, Thread}; 14 use crate::ActivateError; 15 16 pub(crate) fn spawn_virtio_thread<F>( 17 name: &str, 18 seccomp_action: &SeccompAction, 19 thread_type: Thread, 20 epoll_threads: &mut Vec<JoinHandle<()>>, 21 exit_evt: &EventFd, 22 f: F, 23 ) -> Result<(), ActivateError> 24 where 25 F: FnOnce() -> std::result::Result<(), EpollHelperError>, 26 F: Send + 'static, 27 { 28 let seccomp_filter = get_seccomp_filter(seccomp_action, thread_type) 29 .map_err(ActivateError::CreateSeccompFilter)?; 30 31 let thread_exit_evt = exit_evt 32 .try_clone() 33 .map_err(ActivateError::CloneExitEventFd)?; 34 let thread_name = name.to_string(); 35 36 thread::Builder::new() 37 .name(name.to_string()) 38 .spawn(move || { 39 if !seccomp_filter.is_empty() { 40 if let Err(e) = apply_filter(&seccomp_filter) { 41 error!("Error applying seccomp filter: {:?}", e); 42 thread_exit_evt.write(1).ok(); 43 return; 44 } 45 } 46 match std::panic::catch_unwind(AssertUnwindSafe(f)) { 47 Err(_) => { 48 error!("{} thread panicked", thread_name); 49 thread_exit_evt.write(1).ok(); 50 } 51 Ok(r) => { 52 if let Err(e) = r { 53 error!("Error running worker: {:?}", e); 54 thread_exit_evt.write(1).ok(); 55 } 56 } 57 }; 58 }) 59 .map(|thread| epoll_threads.push(thread)) 60 .map_err(|e| { 61 error!("Failed to spawn thread for {}: {}", name, e); 62 ActivateError::ThreadSpawn(e) 63 }) 64 } 65