mirror of
https://github.com/open-goal/jak-project
synced 2026-06-25 18:14:34 -04:00
game/debugger: handle uncaught loader thread exceptions and better handle that situation on the windows debugger (#2075)
This commit is contained in:
@@ -471,12 +471,14 @@ bool check_stopped(const ThreadID& tid, SignalInfo* out) {
|
||||
{
|
||||
auto exc = debugEvent.u.Exception.ExceptionRecord.ExceptionCode;
|
||||
if (is_other) {
|
||||
if (exc == EXCEPTION_BREAKPOINT) {
|
||||
out->kind = SignalInfo::BREAK;
|
||||
} else {
|
||||
// ignore exceptions outside goal thread
|
||||
ignore_debug_event();
|
||||
}
|
||||
ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId,
|
||||
DBG_EXCEPTION_NOT_HANDLED);
|
||||
// if (exc == EXCEPTION_BREAKPOINT) {
|
||||
// out->kind = SignalInfo::BREAK;
|
||||
// } else {
|
||||
// // ignore exceptions outside goal thread
|
||||
// ignore_debug_event();
|
||||
// }
|
||||
} else {
|
||||
switch (exc) {
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
|
||||
@@ -143,18 +143,18 @@ void ReplWrapper::init_default_settings() {
|
||||
// - https://github.com/ClickHouse/ClickHouse/blob/master/base/base/ReplxxLineReader.cpp#L366
|
||||
repl.set_word_break_characters(" \t");
|
||||
// Setup default keybinds
|
||||
// (test-play) : Ctrl-P
|
||||
// (test-play) : Ctrl-T
|
||||
repl.bind_key(Replxx::KEY::control('T'), commit_text_action("(test-play)"));
|
||||
// (e) : Ctrl-Q
|
||||
repl.bind_key(Replxx::KEY::control('Q'), commit_text_action("(e)"));
|
||||
// (lt) : Ctrl-G
|
||||
// (lt) : Ctrl-L
|
||||
repl.bind_key(Replxx::KEY::control('L'), commit_text_action("(lt)"));
|
||||
/// (:stop) : Ctrl-H
|
||||
/// (:stop) : Ctrl-W
|
||||
repl.bind_key(Replxx::KEY::control('W'), commit_text_action("(:stop)"));
|
||||
// (dbgc) : Ctrl-F
|
||||
// (dbgc) : Ctrl-G
|
||||
repl.bind_key(Replxx::KEY::control('G'), commit_text_action("(dbgc)"));
|
||||
// (:di) : Ctrl-B
|
||||
repl.bind_key(Replxx::KEY::control('B'), commit_text_action("(:di)"));
|
||||
// (mi) : Ctrl-M
|
||||
// (mi) : Ctrl-N
|
||||
repl.bind_key(Replxx::KEY::control('N'), commit_text_action("(mi)"));
|
||||
}
|
||||
|
||||
@@ -461,7 +461,7 @@
|
||||
115, // goto L55
|
||||
121,
|
||||
131
|
||||
],
|
||||
],
|
||||
"(anon-function 4 gun-states)": [94, 96, 98],
|
||||
"target-board-handler": [
|
||||
13, 14, 18
|
||||
|
||||
@@ -5377,9 +5377,7 @@
|
||||
[11, "v1", "drawable-tree-instance-shrub"],
|
||||
[38, "v1", "drawable-tree-instance-tie"]
|
||||
],
|
||||
"dma-add-process-drawable-hud": [
|
||||
[11, "a0", "foreground-work"]
|
||||
],
|
||||
"dma-add-process-drawable-hud": [[11, "a0", "foreground-work"]],
|
||||
"find-instance-by-index": [
|
||||
[26, "t1", "drawable-tree-instance-shrub"],
|
||||
[40, "t1", "drawable-tree-instance-tie"]
|
||||
@@ -5395,15 +5393,9 @@
|
||||
[[44, 64], "s1", "drawable-inline-array-instance-tie"],
|
||||
[[331, 450], "s5", "prototype-bucket-tie"]
|
||||
],
|
||||
"set-shadow-by-name": [
|
||||
[7, "v1", "process-drawable"]
|
||||
],
|
||||
"get-shadow-by-name": [
|
||||
[7, "v1", "process-drawable"]
|
||||
],
|
||||
"(anon-function 2 memory-usage)": [
|
||||
[211, "v1", "collide-shape-moving"]
|
||||
],
|
||||
"set-shadow-by-name": [[7, "v1", "process-drawable"]],
|
||||
"get-shadow-by-name": [[7, "v1", "process-drawable"]],
|
||||
"(anon-function 2 memory-usage)": [[211, "v1", "collide-shape-moving"]],
|
||||
"(method 9 screen-filter)": [
|
||||
[[25, 31], "a0", "dma-packet"],
|
||||
[[34, 40], "a0", "gs-gif-tag"],
|
||||
|
||||
@@ -101,66 +101,70 @@ std::vector<LevelData*> Loader::get_in_use_levels() {
|
||||
* This is used for file I/O and unpacking.
|
||||
*/
|
||||
void Loader::loader_thread() {
|
||||
while (!m_want_shutdown) {
|
||||
std::unique_lock<std::mutex> lk(m_loader_mutex);
|
||||
try {
|
||||
while (!m_want_shutdown) {
|
||||
std::unique_lock<std::mutex> lk(m_loader_mutex);
|
||||
|
||||
// this will keep us asleep until we've got a level to load.
|
||||
m_loader_cv.wait(lk, [&] { return !m_level_to_load.empty() || m_want_shutdown; });
|
||||
if (m_want_shutdown) {
|
||||
return;
|
||||
}
|
||||
std::string lev = m_level_to_load;
|
||||
// don't hold the lock while reading the file.
|
||||
lk.unlock();
|
||||
|
||||
// simulate slower hard drive (so that the loader thread can lose to the game loads)
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1500));
|
||||
|
||||
// load the fr3 file
|
||||
Timer disk_timer;
|
||||
auto data =
|
||||
file_util::read_binary_file(m_base_path / fmt::format("{}.fr3", uppercase_string(lev)));
|
||||
double disk_load_time = disk_timer.getSeconds();
|
||||
|
||||
// the FR3 files are compressed
|
||||
Timer decomp_timer;
|
||||
auto decomp_data = compression::decompress_zstd(data.data(), data.size());
|
||||
double decomp_time = decomp_timer.getSeconds();
|
||||
|
||||
// Read back into the tfrag3::Level structure
|
||||
Timer import_timer;
|
||||
auto result = std::make_unique<tfrag3::Level>();
|
||||
Serializer ser(decomp_data.data(), decomp_data.size());
|
||||
result->serialize(ser);
|
||||
double import_time = import_timer.getSeconds();
|
||||
|
||||
// and finally "unpack", which creates the vertex data we'll upload to the GPU
|
||||
Timer unpack_timer;
|
||||
for (auto& tie_tree : result->tie_trees) {
|
||||
for (auto& tree : tie_tree) {
|
||||
tree.unpack();
|
||||
// this will keep us asleep until we've got a level to load.
|
||||
m_loader_cv.wait(lk, [&] { return !m_level_to_load.empty() || m_want_shutdown; });
|
||||
if (m_want_shutdown) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto& t_tree : result->tfrag_trees) {
|
||||
for (auto& tree : t_tree) {
|
||||
tree.unpack();
|
||||
std::string lev = m_level_to_load;
|
||||
// don't hold the lock while reading the file.
|
||||
lk.unlock();
|
||||
|
||||
// simulate slower hard drive (so that the loader thread can lose to the game loads)
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(1500));
|
||||
|
||||
// load the fr3 file
|
||||
Timer disk_timer;
|
||||
auto data =
|
||||
file_util::read_binary_file(m_base_path / fmt::format("{}.fr3", uppercase_string(lev)));
|
||||
double disk_load_time = disk_timer.getSeconds();
|
||||
|
||||
// the FR3 files are compressed
|
||||
Timer decomp_timer;
|
||||
auto decomp_data = compression::decompress_zstd(data.data(), data.size());
|
||||
double decomp_time = decomp_timer.getSeconds();
|
||||
|
||||
// Read back into the tfrag3::Level structure
|
||||
Timer import_timer;
|
||||
auto result = std::make_unique<tfrag3::Level>();
|
||||
Serializer ser(decomp_data.data(), decomp_data.size());
|
||||
result->serialize(ser);
|
||||
double import_time = import_timer.getSeconds();
|
||||
|
||||
// and finally "unpack", which creates the vertex data we'll upload to the GPU
|
||||
Timer unpack_timer;
|
||||
for (auto& tie_tree : result->tie_trees) {
|
||||
for (auto& tree : tie_tree) {
|
||||
tree.unpack();
|
||||
}
|
||||
}
|
||||
for (auto& t_tree : result->tfrag_trees) {
|
||||
for (auto& tree : t_tree) {
|
||||
tree.unpack();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& shrub_tree : result->shrub_trees) {
|
||||
shrub_tree.unpack();
|
||||
}
|
||||
fmt::print(
|
||||
"------------> Load from file: {:.3f}s, import {:.3f}s, decomp {:.3f}s unpack {:.3f}s\n",
|
||||
disk_load_time, import_time, decomp_time, unpack_timer.getSeconds());
|
||||
for (auto& shrub_tree : result->shrub_trees) {
|
||||
shrub_tree.unpack();
|
||||
}
|
||||
fmt::print(
|
||||
"------------> Load from file: {:.3f}s, import {:.3f}s, decomp {:.3f}s unpack {:.3f}s\n",
|
||||
disk_load_time, import_time, decomp_time, unpack_timer.getSeconds());
|
||||
|
||||
// grab the lock again
|
||||
lk.lock();
|
||||
// move this level to "initializing" state.
|
||||
m_initializing_tfrag3_levels[lev] = std::make_unique<LevelData>(); // reset load state
|
||||
m_initializing_tfrag3_levels[lev]->level = std::move(result);
|
||||
m_level_to_load = "";
|
||||
m_file_load_done_cv.notify_all();
|
||||
// grab the lock again
|
||||
lk.lock();
|
||||
// move this level to "initializing" state.
|
||||
m_initializing_tfrag3_levels[lev] = std::make_unique<LevelData>(); // reset load state
|
||||
m_initializing_tfrag3_levels[lev]->level = std::move(result);
|
||||
m_level_to_load = "";
|
||||
m_file_load_done_cv.notify_all();
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
ASSERT_MSG(false, fmt::format("Exception {} encountered in loader_thread", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user