bheisler / RustaCUDA

Rusty wrapper for the CUDA Driver API
Apache License 2.0
765 stars 58 forks source link

Panic during CUDA types' Drop implementations inside thread-local storage #68

Open WilliamVenner opened 2 years ago

WilliamVenner commented 2 years ago

Hi, I'm writing a Python module that uses RustaCUDA and I am running into an issue where the library panics when Python is exiting.

I store some RustaCUDA state in a thread-local storage key, like this:

struct CUDAInstance {
    module: Module,
    _context: Context
}
impl CUDAInstance {
    fn init() -> CudaResult<CUDAInstance> {
        rustacuda::init(CudaFlags::empty())?;
        let device = Device::get_device(0)?;
        let context = Context::create_and_push(ContextFlags::MAP_HOST | ContextFlags::SCHED_AUTO, device)?;

        Ok(CUDAInstance {
            _context: context,
            module: {
                const PTX: &str = concat!(include_str!(concat!("../cuda/cuda.ptx")), "\0");
                Module::load_from_string(unsafe { std::ffi::CStr::from_ptr(PTX.as_ptr() as *const i8) })?
            }
        })
    }
}
thread_local! {
    static CUDA: Result<CUDAInstance, CudaError> = CUDAInstance::init();
}

Everything works as expected, except that when Python has finished executing the script, Windows runs the thread-local storage destructor functions and RustaCUDA panics.

I would guess that CUDA has already been informed that the program is exiting and deinitializes itself, therefore the drop implementations panic, as they don't check if the types have already been deinitialized.

thread '<unnamed>' panicked at 'Failed to unload CUDA module: Deinitialized', C:\Users\William\.cargo\registry\src\github.com-1ecc6299db9ec823\rustacuda-0.1.3\src\module.rs:223:18
stack backtrace:
   0: std::panicking::begin_panic_handler
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\std\src\panicking.rs:584
   1: core::panicking::panic_fmt
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\core\src\panicking.rs:143
   2: core::result::unwrap_failed
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\core\src\result.rs:1749
   3: enum$<core::result::Result<tuple$<>,enum$<rustacuda::error::CudaError> >, 1, 100101, Err>::expect
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\result.rs:1022
   4: rustacuda::module::impl$1::drop
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\ptr\mod.rs:188
   5: core::ptr::drop_in_place
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\ptr\mod.rs:188
   6: core::ptr::drop_in_place
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\ptr\mod.rs:188
   7: core::ptr::drop_in_place
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\ptr\mod.rs:188
   8: core::ptr::drop_in_place
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\ptr\mod.rs:188
   9: core::mem::drop
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\core\src\mem\mod.rs:909
  10: std::thread::local::fast::destroy_value<enum$<core::result::Result<smh_vision_gpu::cuda::CUDAInstance,enum$<rustacuda::error::CudaError> > > >
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\library\std\src\thread\local.rs:669
  11: std::sys::windows::thread_local_dtor::run_keyless_dtors
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\std\src\sys\windows\thread_local_dtor.rs:24
  12: std::sys::windows::thread_local_key::on_tls_callback
             at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c\/library\std\src\sys\windows\thread_local_key.rs:200
  13: RtlInitializeConditionVariable
  14: RtlActivateActivationContextUnsafeFast
  15: LdrLoadAlternateResourceModuleEx
  16: LdrShutdownProcess
  17: RtlExitUserProcess
  18: ExitProcess
  19: exit
  20: exit
  21: <unknown>
  22: BaseThreadInitThunk
  23: RtlUserThreadStart
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.