| 287 | } |
| 288 | |
| 289 | OPENKNEEBOARD_NOINLINE |
| 290 | static std::string GetFatalLogContents( |
| 291 | const CrashMeta& meta, |
| 292 | const FatalData& fatal) noexcept { |
| 293 | static std::atomic_flag sRecursing; |
| 294 | if (sRecursing.test_and_set()) { |
| 295 | OutputDebugStringA( |
| 296 | std::format("💀💀 FATAL DURING FATAL: {}", fatal.mMessage).c_str()); |
| 297 | fast_fail(); |
| 298 | } |
| 299 | |
| 300 | std::string blameString; |
| 301 | if (fatal.mBlameLocation) { |
| 302 | blameString = std::format("{}", *fatal.mBlameLocation); |
| 303 | } else { |
| 304 | const auto& caller = meta.mStacktrace.at(1); |
| 305 | blameString = std::format( |
| 306 | "{}:{} - {}", |
| 307 | caller->source_file(), |
| 308 | caller->source_line(), |
| 309 | caller->description()); |
| 310 | } |
| 311 | |
| 312 | // Let's just get the basics out early in case anything else goes wrong |
| 313 | dprint("💀 FATAL: {} @ {}", fatal.mMessage, blameString); |
| 314 | |
| 315 | std::stringstream f; |
| 316 | |
| 317 | const auto executable = Filesystem::GetCurrentExecutablePath(); |
| 318 | |
| 319 | f << std::format( |
| 320 | "{} (PID {}) crashed at {:%Y%m%dT%H%M%S}\n\n", |
| 321 | executable.filename(), |
| 322 | meta.mPID, |
| 323 | meta.mNow) |
| 324 | << std::format("💀 FATAL: {}\n", fatal.mMessage); |
| 325 | |
| 326 | std::unique_ptr<wchar_t, decltype(&LocalFree)> threadDescriptionBuf { |
| 327 | nullptr, &LocalFree}; |
| 328 | GetThreadDescription(GetCurrentThread(), std::out_ptr(threadDescriptionBuf)); |
| 329 | const auto threadDescription = winrt::to_string(threadDescriptionBuf.get()); |
| 330 | |
| 331 | f << "\n" |
| 332 | << "Metadata\n" |
| 333 | << "========\n\n" |
| 334 | << std::format("Executable: {}\n", executable) |
| 335 | << std::format("Module: {}\n", meta.mModulePath) |
| 336 | << std::format( |
| 337 | "Thread: {} {}\n", |
| 338 | std::this_thread::get_id(), |
| 339 | threadDescription.empty() ? "[no description]"s |
| 340 | : std::format("(\"{}\")", threadDescription)) |
| 341 | << std::format("Blame frame: {}\n", blameString) |
| 342 | << std::format("OKB Version: {}\n", Version::ReleaseName); |
| 343 | |
| 344 | f << "\n" |
| 345 | << "Stack Trace\n" |
| 346 | << "===========\n\n" |
nothing calls this directly
no test coverage detected