|
12 | 12 | #ifdef __APPLE__ |
13 | 13 | #include <dlfcn.h> |
14 | 14 | #endif |
| 15 | +#ifdef _WIN32 |
| 16 | +#include <windows.h> |
| 17 | +#endif |
15 | 18 |
|
16 | 19 | #include "eden/fs/rust/backtrace_ffi/src/lib.rs.h" |
17 | 20 |
|
18 | | -#if defined(__linux__) || defined(__APPLE__) |
19 | | - |
20 | 21 | namespace { |
21 | | -// Common: onThrow() captures a raw backtrace via Rust FFI. |
22 | | -// Re-entrancy is handled by the Rust CapturingGuard in capture_backtrace(). |
23 | 22 | void onThrow() { |
24 | 23 | constexpr size_t kMaxStackDepth = 64; |
25 | 24 | facebook::eden::capture_backtrace(kMaxStackDepth); |
@@ -68,9 +67,51 @@ __cxa_throw(void* thrownException, void* type, void (*destructor)(void*)) { |
68 | 67 | __builtin_unreachable(); |
69 | 68 | } |
70 | 69 |
|
71 | | -#endif // platform hooks |
| 70 | +#elif defined(_WIN32) |
| 71 | +// Windows: Vectored Exception Handler catches C++ exceptions (SEH 0xE06D7363). |
| 72 | + |
| 73 | +constexpr DWORD kCppExceptionCode = 0xE06D7363; |
| 74 | + |
| 75 | +LONG WINAPI cppExceptionHandler(PEXCEPTION_POINTERS info) { |
| 76 | + if (info && info->ExceptionRecord && |
| 77 | + info->ExceptionRecord->ExceptionCode == kCppExceptionCode) { |
| 78 | + onThrow(); |
| 79 | + } |
| 80 | + return EXCEPTION_CONTINUE_SEARCH; |
| 81 | +} |
| 82 | + |
| 83 | +// AddVectoredExceptionHandler first parameter: CALL_FIRST (1) registers our |
| 84 | +// handler at the front of the VEH list so it runs before other handlers, |
| 85 | +// ensuring we capture the stack trace before the exception is modified. |
| 86 | +// See: |
| 87 | +// https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-addvectoredexceptionhandler |
| 88 | +#define CALL_FIRST 1 |
| 89 | + |
| 90 | +struct VehRegistrar { |
| 91 | + PVOID handle_ = nullptr; |
| 92 | + VehRegistrar(const VehRegistrar&) = delete; |
| 93 | + VehRegistrar& operator=(const VehRegistrar&) = delete; |
| 94 | + VehRegistrar(VehRegistrar&&) = delete; |
| 95 | + VehRegistrar& operator=(VehRegistrar&&) = delete; |
| 96 | + |
| 97 | + VehRegistrar() { |
| 98 | + handle_ = AddVectoredExceptionHandler(CALL_FIRST, cppExceptionHandler); |
| 99 | + if (!handle_) { |
| 100 | + fprintf( |
| 101 | + stderr, |
| 102 | + "Failed to register VEH for throw-site stack trace capture\n"); |
| 103 | + } |
| 104 | + } |
| 105 | + ~VehRegistrar() { |
| 106 | + if (handle_) { |
| 107 | + RemoveVectoredExceptionHandler(handle_); |
| 108 | + } |
| 109 | + } |
| 110 | +}; |
| 111 | + |
| 112 | +static VehRegistrar vehRegistrar; |
72 | 113 |
|
73 | | -#endif // defined(__linux__) || defined(__APPLE__) |
| 114 | +#endif // platform hooks |
74 | 115 |
|
75 | 116 | namespace facebook::eden { |
76 | 117 |
|
|
0 commit comments