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