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
spawn_virtio_thread<F>( name: &str, seccomp_action: &SeccompAction, thread_type: Thread, epoll_threads: &mut Vec<JoinHandle<()>>, exit_evt: &EventFd, f: F, ) -> Result<(), ActivateError> where F: FnOnce() -> std::result::Result<(), EpollHelperError>, F: Send + 'static,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