A C# application with an Avalonia desktop user interface calls a Rust library function via Rust's Foreign Function Interface (FFI). When the application is run from an IDE (JetBrains Rider or Visual studio) in Windows, the Rust library function panics on calling std::thread::spawn. The error message is
thread '<unnamed>' panicked at ... .rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\std\src\thread\mod.rs:729:
failed to spawn thread: Os { code: 5, kind: PermissionDenied, message: "Access is denied." }
The problem does not occur when the application is run directly rather than via an IDE. Nor does it occur when the same Rust library function is called in via an IDE in a console application or unit tests.
The workaround is to use tokio::spawn instead of std::thread::spawn.
I'd prefer not to be dependent on the tokio runtime, as the Rust library has no other use for it. Perhaps that should not really be of concern. But I thought I should report this error anyway.
I realise this may not be a Rust problem. But I reckon this forum is a good first place to get advice.
That looks like a permission/sandboxing issue rather than a Rust bug.
When running GUI apps from Rider or Visual Studio, the IDE sometimes launches them in a restricted environment (kind of like a lightweight container) where direct system calls such as CreateThread can fail with “Access is denied.” That would explain why std::thread::spawn panics only in that context, but works fine when you run the binary directly.
tokio::spawn happens to avoid it because its runtime creates worker threads ahead of time.
You might check the debug host settings in your IDE — for example, whether Avalonia is being run via a “sandboxed process” or using Windows Application Model isolation.
@veecore Thanks for your explanation of why tokio::spawn works in this context and std::thread::spawn does not. That makes sense.
I can't see anything in JetBrains Rider or Visual Studio settings that might fix this. If I wanted to investigate this further, my next step would be to ask on the Rider forum, where JetBrains support staff are very helpful. However, even if there are settings in both IDEs that can fix this, I would rather keep usage simple for C# developers: the Rust library I'm developing and its C# wrapper class are intended to become open source.
As I have no other use for Tokio, I have replaced tokio::spawn with rayon::spawn, as Rayon also uses a thread pool created in advance. It works. Much better!