This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new d063f470 [FFI][FIX] Backtrace: refresh DbgHelp modules, tolerate bad 
TVM_TRACEBACK_LIMIT, match object_is_not_callable exactly (#763)
d063f470 is described below

commit d063f470b4973bda02da85b7d7e61b8de927acd0
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Sep 7 20:54:22 2026 -0400

    [FFI][FIX] Backtrace: refresh DbgHelp modules, tolerate bad 
TVM_TRACEBACK_LIMIT, match object_is_not_callable exactly (#763)
    
    Four small fixes from the follow-up report on #727:
    
    - `backtrace_win.cc`: `SymRefreshModuleList` before `StackWalk64`. The
    session is created once, so a DLL loaded after the first backtrace was
    unknown to DbgHelp; `StackWalk64` needs its unwind tables, so the trace
    truncated at that frame.
    - `backtrace_win.cc`: the explicit caller frame goes through
    `ShouldExcludeFrame`, as `backtrace.cc` already does.
    - `backtrace_utils.h`: `TVM_TRACEBACK_LIMIT` parsed with `strtol`,
    default on invalid input. `std::stoi` threw inside the error reporter
    and terminated the process.
    - `backtrace_utils.h`: full-identifier match for
    `object_is_not_callable`; the 11-character prefix also matched other
    `object_is_n...` symbols.
    
    No behaviour change for valid inputs.
---
 src/ffi/backtrace_utils.h | 12 ++++++++++--
 src/ffi/backtrace_win.cc  |  9 ++++++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/ffi/backtrace_utils.h b/src/ffi/backtrace_utils.h
index 346d51c7..16135c35 100644
--- a/src/ffi/backtrace_utils.h
+++ b/src/ffi/backtrace_utils.h
@@ -26,6 +26,8 @@
 
 #include <tvm/ffi/base_details.h>
 
+#include <climits>
+#include <cstdlib>
 #include <cstring>
 #include <sstream>
 #include <string>
@@ -41,7 +43,13 @@ namespace ffi {
 
 inline int32_t GetBacktraceLimit() {
   if (const char* env = std::getenv("TVM_TRACEBACK_LIMIT")) {
-    return std::stoi(env);
+    char* end = nullptr;
+    long value = std::strtol(env, &end, 10);  // NOLINT(runtime/int)
+    // An empty, non-numeric, negative, or out-of-range value falls back to the
+    // default rather than throwing from inside the error reporter.
+    if (end != env && *end == '\0' && value >= 0 && value <= INT32_MAX) {
+      return static_cast<int32_t>(value);
+    }
   }
   return 512;
 }
@@ -120,7 +128,7 @@ inline bool DetectFFIBoundary(const char* filename, const 
char* symbol) {
     if (strncmp(symbol, "slot_tp_call", 12) == 0) {
       return true;
     }
-    if (strncmp(symbol, "object_is_not_callable", 11) == 0) {
+    if (strncmp(symbol, "object_is_not_callable", 22) == 0) {
       return true;
     }
     // Python interpreter stack frames
diff --git a/src/ffi/backtrace_win.cc b/src/ffi/backtrace_win.cc
index 6f782b90..9fc2ad53 100644
--- a/src/ffi/backtrace_win.cc
+++ b/src/ffi/backtrace_win.cc
@@ -89,7 +89,9 @@ const TVMFFIByteArray* TVMFFIBacktrace(const char* filename, 
int lineno, const c
     // need to skip TVMFFIBacktrace and the caller function
     // which is already included in filename and func
     backtrace.skip_frame_count = 2;
-    backtrace.Append(filename, func, lineno);
+    if (!tvm::ffi::ShouldExcludeFrame(filename, func)) {
+      backtrace.Append(filename, func, lineno);
+    }
   }
 
   HANDLE thread = GetCurrentThread();
@@ -105,6 +107,11 @@ const TVMFFIByteArray* TVMFFIBacktrace(const char* 
filename, int lineno, const c
     backtrace_array.size = backtrace_str.size();
     return &backtrace_array;
   }
+  // Register modules loaded since the session was created. StackWalk64 needs a
+  // module's unwind tables to step through it, so a DLL DbgHelp does not know
+  // truncates the walk at its first frame rather than just losing the name.
+  SymRefreshModuleList(process);
+
   CONTEXT context = {};
   RtlCaptureContext(&context);
 

Reply via email to