[Mlir-commits] [mlir] [MLIR][ExecutionEngine] Tolerate CUDA_ERROR_DEINITIALIZED in mgpuModuleUnload (PR #190563)

Jared Hoberock llvmlistbot at llvm.org
Mon Apr 6 10:54:00 PDT 2026


https://github.com/jaredhoberock updated https://github.com/llvm/llvm-project/pull/190563

>From 85a7ec62cc20a9697596a351a0d9d177dcff3b5a Mon Sep 17 00:00:00 2001
From: Jared Hoberock <jaredhoberock at gmail.com>
Date: Mon, 6 Apr 2026 12:53:50 -0500
Subject: [PATCH] [MLIR][ExecutionEngine] Tolerate CUDA context shutdown errors
 in resource cleanup
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

During program exit, CUDA resource cleanup functions (module unload,
stream/event destroy, etc.) may be called after the CUDA primary context
has already been destroyed. This produces spurious error messages like
'cuModuleUnload(module)' failed with 'CUDA_ERROR_DEINITIALIZED' or
'cuEventDestroy(event)' failed with 'CUDA_ERROR_CONTEXT_IS_DESTROYED'.

These errors are benign — all resources are already freed when the
context is destroyed.

Add CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN macro that silences both
CUDA_ERROR_DEINITIALIZED (4) and CUDA_ERROR_CONTEXT_IS_DESTROYED (709),
and apply it to the five cleanup wrappers: mgpuModuleUnload,
mgpuStreamDestroy, mgpuStreamWaitEvent, mgpuEventDestroy, and
mgpuEventSynchronize.

Re-enable FileCheck in async.mlir integration test.

Fixes #170833, fixes #190563.
---
 .../ExecutionEngine/CudaRuntimeWrappers.cpp   | 33 ++++++++++++++++---
 mlir/test/Integration/GPU/CUDA/async.mlir     |  7 ++--
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp b/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp
index 6307e0b59f3d2..4363e841d69a7 100644
--- a/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp
+++ b/mlir/lib/ExecutionEngine/CudaRuntimeWrappers.cpp
@@ -45,6 +45,29 @@
     fprintf(stderr, "'%s' failed with '%s'\n", #expr, name);                   \
   }(expr)
 
+/// Helper to check if a CUDA error is due to the context being destroyed
+/// during program shutdown. Both CUDA_ERROR_DEINITIALIZED and
+/// CUDA_ERROR_CONTEXT_IS_DESTROYED indicate that the CUDA context has been
+/// torn down and any associated resources are already freed.
+static bool isCudaContextShutdownError(CUresult result) {
+  return result == CUDA_ERROR_DEINITIALIZED ||
+         result == CUDA_ERROR_CONTEXT_IS_DESTROYED;
+}
+
+/// Like CUDA_REPORT_IF_ERROR, but silences errors caused by CUDA context
+/// shutdown. These errors are benign when they occur during program exit,
+/// as all resources are freed with the context.
+#define CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN(expr)                             \
+  [](CUresult result) {                                                        \
+    if (!result || isCudaContextShutdownError(result))                         \
+      return;                                                                  \
+    const char *name = nullptr;                                                \
+    cuGetErrorName(result, &name);                                             \
+    if (!name)                                                                 \
+      name = "<unknown>";                                                      \
+    fprintf(stderr, "'%s' failed with '%s'\n", #expr, name);                   \
+  }(expr)
+
 #define CUSPARSE_REPORT_IF_ERROR(expr)                                         \
   {                                                                            \
     cusparseStatus_t status = (expr);                                          \
@@ -146,7 +169,7 @@ mgpuModuleLoadJIT(void *data, int optLevel, size_t /*assmeblySize*/) {
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuModuleUnload(CUmodule module) {
-  CUDA_REPORT_IF_ERROR(cuModuleUnload(module));
+  CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN(cuModuleUnload(module));
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT CUfunction
@@ -199,7 +222,7 @@ extern "C" MLIR_CUDA_WRAPPERS_EXPORT CUstream mgpuStreamCreate() {
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuStreamDestroy(CUstream stream) {
-  CUDA_REPORT_IF_ERROR(cuStreamDestroy(stream));
+  CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN(cuStreamDestroy(stream));
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void
@@ -209,7 +232,7 @@ mgpuStreamSynchronize(CUstream stream) {
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuStreamWaitEvent(CUstream stream,
                                                               CUevent event) {
-  CUDA_REPORT_IF_ERROR(cuStreamWaitEvent(stream, event, /*flags=*/0));
+  CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN(cuStreamWaitEvent(stream, event, /*flags=*/0));
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT CUevent mgpuEventCreate() {
@@ -220,11 +243,11 @@ extern "C" MLIR_CUDA_WRAPPERS_EXPORT CUevent mgpuEventCreate() {
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuEventDestroy(CUevent event) {
-  CUDA_REPORT_IF_ERROR(cuEventDestroy(event));
+  CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN(cuEventDestroy(event));
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuEventSynchronize(CUevent event) {
-  CUDA_REPORT_IF_ERROR(cuEventSynchronize(event));
+  CUDA_REPORT_IF_ERROR_IGNORE_SHUTDOWN(cuEventSynchronize(event));
 }
 
 extern "C" MLIR_CUDA_WRAPPERS_EXPORT void mgpuEventRecord(CUevent event,
diff --git a/mlir/test/Integration/GPU/CUDA/async.mlir b/mlir/test/Integration/GPU/CUDA/async.mlir
index 3e45b5af5826c..5acadd61f432c 100644
--- a/mlir/test/Integration/GPU/CUDA/async.mlir
+++ b/mlir/test/Integration/GPU/CUDA/async.mlir
@@ -8,11 +8,8 @@
 // RUN:   --shared-libs=%mlir_cuda_runtime \
 // RUN:   --shared-libs=%mlir_async_runtime \
 // RUN:   --shared-libs=%mlir_runner_utils \
-// RUN:   --entry-point-result=void -O0
-// RUN:
-// This test is overly flaky right now and needs investigation, skipping FileCheck.
-// See: https://github.com/llvm/llvm-project/issues/170833
-// DISABLED: | FileCheck %s
+// RUN:   --entry-point-result=void -O0 \
+// RUN: | FileCheck %s
 
 func.func @main() {
   %c0    = arith.constant 0 : index



More information about the Mlir-commits mailing list