Repository navigation
Open
Labels
platform: macosmacOS specific issuesmacOS specific issuesplugin: clipboard-managertype: bugSomething isn't workingSomething isn't working
Description
Describe the bug
[Bug] Clipboard operations crash on macOS due to thread safety violation
Describe the bug
The application crashes with EXC_BAD_ACCESS (SIGSEGV) on macOS when using writeText() from @tauri-apps/plugin-clipboard-manager. The crash occurs due to a race condition between the clipboard plugin (running on a tokio worker thread) and WebKit's pasteboard monitoring (running on the main thread).
Reproduction
- Create a Tauri 2.x application with
tauri-plugin-clipboard-manager - Call
writeText()from the frontend while the WebView is active - The app may crash intermittently, especially under frequent clipboard operations
Expected behavior
Clipboard operations should complete without crashing the application.
Platform and versions
| Component | Version |
|---|---|
| OS | macOS 15.6.1 (Sequoia) |
| Architecture | Apple Silicon (running x86_64 via Rosetta 2) |
| Tauri | 2.9.3 |
| tauri-plugin-clipboard-manager | 2.3.2 |
| arboard | 3.x |
| Rust | 1.77.2+ |
Crash Report
Exception Info
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00006e227e7baba0
Termination Reason: SIGNAL 11 Segmentation fault: 11
Thread 0 (Main Thread - WebKit)
0 libobjc.A.dylib objc_msgSend + 16
1 libobjc.A.dylib +[NSObject self] + 0
2 AppKit -[NSPasteboard(NSInternal) _pasteboardWithName:uniqueId:] + 264
3 AppKit +[NSPasteboard pasteboardWithName:] + 44
4 WebKit WebKit::WebPasteboardProxy::getPasteboardChangeCount(...) + 52
5 WebKit WebKit::WebPasteboardProxy::didReceiveSyncMessage(...) + 1204
...
14 JavaScriptCore WTF::RunLoop::performWork() + 204
...
27 libdyld.dylib start + 1
Thread 11 (tokio-runtime-worker - Concurrent)
0 libsystem_kernel.dylib mach_msg2_trap + 8
...
12 arboard arboard::platform::osx::Set::text + 492
13 arboard arboard::Clipboard::set_text + 32
14 tauri_plugin_clipboard_manager tauri_plugin_clipboard_manager::desktop::Clipboard<R>::write_text + 136
...
Root Cause Analysis
1. NSPasteboard is NOT thread-safe
From Apple's documentation:
All AppKit objects, including NSPasteboard, should only be accessed from the main thread.
2. Tauri async commands run on tokio worker threads
// commands.rs
#[command]
pub(crate) async fn write_text<R: Runtime>(
_app: AppHandle<R>,
clipboard: State<'_, Clipboard<R>>,
text: &str,
...
) -> Result<()> {
clipboard.write_text(text) // ← Executed on tokio worker thread
}3. arboard directly calls NSPasteboard
// desktop.rs
pub fn write_text<'a, T: Into<Cow<'a, str>>>(&self, text: T) -> crate::Result<()> {
match &self.clipboard {
Ok(clipboard) => clipboard
.lock()
.unwrap()
.as_mut()
.unwrap()
.set_text(text) // → arboard::Clipboard::set_text()
// → NSPasteboard::writeObjects() on worker thread!
.map_err(Into::into),
...
}
}4. WebKit monitors clipboard on main thread
WebKit's WebPasteboardProxy::getPasteboardChangeCount() periodically checks the clipboard from the main thread to implement:
pasteeventsnavigator.clipboardAPI- Clipboard permission checks
Race Condition Timeline
T0: Frontend calls writeText()
T1: Tauri IPC receives request, schedules to tokio runtime
T2: tokio worker (Thread 11) executes:
→ clipboard.write_text()
→ arboard::Clipboard::set_text()
→ NSPasteboard::writeObjects() ← On worker thread!
T3: Simultaneously, WebKit (Thread 0) executes:
→ WebPasteboardProxy::getPasteboardChangeCount()
→ Accesses NSPasteboard internal state
T4: Race condition! Both threads access NSPasteboard concurrently
T5: Thread 0 accesses memory being modified by Thread 11
T6: SIGSEGV at invalid address
AI Suggested Fix
Dispatch clipboard operations to the main thread on macOS:
#[cfg(target_os = "macos")]
use dispatch::Queue;
impl<R: Runtime> Clipboard<R> {
pub fn write_text<'a, T: Into<Cow<'a, str>>>(&self, text: T) -> crate::Result<()> {
#[cfg(target_os = "macos")]
{
let text_owned = text.into().into_owned();
// Execute clipboard operation on main thread
Queue::main().exec_sync(move || {
### Reproduction
_No response_
### Expected behavior
_No response_
### Full `tauri info` output
```text
[✔] Environment
- OS: Mac OS 26.2.0 arm64 (X64)
✔ Xcode Command Line Tools: installed
✔ Xcode: 26.1.1
✔ rustc: 1.92.0 (ded5c06cf 2025-12-08)
✔ cargo: 1.92.0 (344c4567c 2025-10-21)
✔ rustup: 1.28.2 (e4f3ad6f8 2025-04-28)
✔ Rust toolchain: stable-aarch64-apple-darwin (default)
- node: 20.19.1
- pnpm: 10.14.0
- npm: 10.8.2
[-] Packages
- tauri 🦀: 2.9.5
- tauri-build 🦀: 2.5.3
- wry 🦀: 0.53.5
- tao 🦀: 0.34.5
- @tauri-apps/api ⱼₛ: 2.9.0 (outdated, latest: 2.9.1)
- @tauri-apps/cli ⱼₛ: 2.9.3 (outdated, latest: 2.9.6)
[-] Plugins
- tauri-plugin-single-instance 🦀: 2.3.6, (outdated, latest: 2.3.7)
- @tauri-apps/plugin-single-instance ⱼₛ: not installed!
- tauri-plugin-os 🦀: 2.3.2
- @tauri-apps/plugin-os ⱼₛ: 2.3.2
- tauri-plugin-updater 🦀: 2.9.0
- @tauri-apps/plugin-updater ⱼₛ: 2.9.0
- tauri-plugin-window-state 🦀: 2.4.1
- @tauri-apps/plugin-window-state ⱼₛ: 2.4.1
- tauri-plugin-deep-link 🦀: 2.4.5, (outdated, latest: 2.4.6)
- @tauri-apps/plugin-deep-link ⱼₛ: 2.4.5 (outdated, latest: 2.4.6)
- tauri-plugin-http 🦀: 2.5.4, (outdated, latest: 2.5.5)
- @tauri-apps/plugin-http ⱼₛ: 2.5.4 (outdated, latest: 2.5.5)
- tauri-plugin-store 🦀: 2.4.1, (outdated, latest: 2.4.2)
- @tauri-apps/plugin-store ⱼₛ: 2.4.1 (outdated, latest: 2.4.2)
- tauri-plugin-dialog 🦀: 2.4.2, (outdated, latest: 2.5.0)
- @tauri-apps/plugin-dialog ⱼₛ: 2.4.2 (outdated, latest: 2.5.0)
- tauri-plugin-websocket 🦀: 2.4.1, (outdated, latest: 2.4.2)
- @tauri-apps/plugin-websocket ⱼₛ: 2.4.1 (outdated, latest: 2.4.2)
- tauri-plugin-fs 🦀: 2.4.4, (outdated, latest: 2.4.5)
- @tauri-apps/plugin-fs ⱼₛ: 2.4.4 (outdated, latest: 2.4.5)
- tauri-plugin-opener 🦀: 2.5.2, (outdated, latest: 2.5.3)
- @tauri-apps/plugin-opener ⱼₛ: 2.5.2 (outdated, latest: 2.5.3)
- tauri-plugin-clipboard-manager 🦀: 2.3.2
- @tauri-apps/plugin-clipboard-manager ⱼₛ: 2.3.2
- tauri-plugin-global-shortcut 🦀: 2.3.1
- @tauri-apps/plugin-global-shortcut ⱼₛ: 2.3.1
- tauri-plugin-upload 🦀: 2.3.2, (outdated, latest: 2.4.0)
- @tauri-apps/plugin-upload ⱼₛ: 2.3.2 (outdated, latest: 2.4.0)
- tauri-plugin-process 🦀: 2.3.1
- @tauri-apps/plugin-process ⱼₛ: 2.3.1Stack trace
Additional context
No response
Reacted by Federico Terzi
Metadata
Metadata
Assignees
Labels
platform: macosmacOS specific issuesmacOS specific issuesplugin: clipboard-managertype: bugSomething isn't workingSomething isn't working
Activity
fix(desktop): route the clipboard through a native command
fix(desktop): route the clipboard through a native command
fix(desktop): macOS copy/paste on WalletConnect, Wizard, CashConnect (#…