使用Tauri时Unicorn结构体跨线程安全问题求助
解决Unicorn结构体作为Tauri全局变量的线程安全问题
编译错误信息
error[E0277]: `Rc<UnsafeCell<UnicornInner<'static, ()>>>` cannot be sent between threads safely --> src\main.rs:76:37 | 76 | fn init_emulator(emulator_instance: State<EmulatorGlobal>) { | ^^^^^^^^^^^^^^^^^^^^^ `Rc<UnsafeCell<UnicornInner<'static, ()>>>` cannot be sent between threads safely | = help: within `Unicorn<'static, ()>`, the trait `Send` is not implemented for `Rc<UnsafeCell<UnicornInner<'static, ()>>>` = note: required because it appears within the type `Unicorn<'static, ()>` = note: required for `std::sync::Mutex<Unicorn<'static, ()>>` to implement `Send` note: required because it appears within the type `EmulatorGlobal` --> src\main.rs:27:8 | 27 | struct EmulatorGlobal(Mutex<Unicorn<'static, ()>>); | ^^^^^^^^^^^^^^ note: required by a bound in `State` --> C:\Users\Aslan\.cargo\registry\src\github.com-1ecc6299db9ec823\tauri-1.2.2\src\state.rs:14:25 | 14 | pub struct State<'r, T: Send + Sync + 'static>(&'r T); | ^^^^ required by this bound in `State`
相关结构体与代码
第三方crate的Unicorn结构体定义:
/// A Unicorn emulator instance. pub struct Unicorn<'a, D: 'a> { inner: Rc<UnsafeCell<UnicornInner<'a, D>>>, }
Tauri全局变量声明:
struct EmulatorGlobal(Mutex<Unicorn<'static, ()>>);
Tauri命令代码:
#[tauri::command] fn init_emulator(emulator_instance: State<EmulatorGlobal>) { let mut unicorn: Unicorn<()> = Unicorn::new(Arch::X86, Mode::MODE_64).expect("ERROR"); }
注:该结构体使用的是alloc::rc::Rc,功能与std::rc::Rc一致
安全的猴子补丁解决方案
问题核心是Unicorn因内部Rc未实现Send,无法满足Tauri全局状态的Send + Sync约束。我们可以通过包装结构体手动实现线程安全trait,前提是通过Mutex保证互斥访问:
// 定义包装结构体,封装Unicorn实例 struct ThreadSafeUnicorn(Unicorn<'static, ()>); // 手动实现Send和Sync // 安全性说明:通过Mutex确保同一时间只有一个线程访问Unicorn实例, // 内部Rc不会被跨线程clone,UnsafeCell的操作处于互斥保护下,因此是安全的 unsafe impl Send for ThreadSafeUnicorn {} unsafe impl Sync for ThreadSafeUnicorn {} // 修改全局变量定义,使用包装后的结构体 struct EmulatorGlobal(Mutex<ThreadSafeUnicorn>); // 更新Tauri命令代码 #[tauri::command] fn init_emulator(mut emulator_instance: State<EmulatorGlobal>) { let unicorn = Unicorn::new(Arch::X86, Mode::MODE_64).expect("ERROR"); // 将实例存入全局变量 *emulator_instance.0.lock().unwrap() = ThreadSafeUnicorn(unicorn); }
关键说明
Mutex提供了线程间的互斥访问保证,避免多线程同时操作UnsafeCell的风险Rc本身不支持跨线程传递,但我们不会跨线程clone这个Rc,只会在同一线程内通过Mutex锁定后访问,因此引用计数操作是线程安全的- 手动实现
Send和Sync是unsafe操作,但基于上述约束,这个实现是安全的
内容的提问来源于stack exchange,提问作者swapgs
相关产品推荐
相关产品推荐

