diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index a442c0a884..d7434a72fc 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -94,7 +94,7 @@ thread_local bool g_tls_access_violation_recovered = false; extern thread_local std::string(*g_tls_log_prefix)(); // Report error and call std::abort(), defined in main.cpp -[[noreturn]] void report_fatal_error(const std::string&); +[[noreturn]] void report_fatal_error(std::string_view); template <> void fmt_class_string::format(std::string& out, u64 arg) @@ -1609,6 +1609,22 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no return true; } +static void append_thread_name(std::string& msg) +{ + if (thread_ctrl::get_current()) + { + fmt::append(msg, "Emu Thread Name: '%s'.\n", thread_ctrl::get_name()); + } + else if (thread_ctrl::is_main()) + { + fmt::append(msg, "Thread: Main Thread"); + } + else + { + fmt::append(msg, "Thread id = %s.\n", std::this_thread::get_id()); + } +} + #ifdef _WIN32 static LONG exception_handler(PEXCEPTION_POINTERS pExp) noexcept @@ -1670,14 +1686,7 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept } } - if (thread_ctrl::get_current()) - { - fmt::append(msg, "Emu Thread Name: '%s'.\n", thread_ctrl::get_name()); - } - - // TODO: Report full thread name if not an emu thread - - fmt::append(msg, "Thread id = %s.\n", std::this_thread::get_id()); + append_thread_name(msg); std::vector modules; for (DWORD size = 256; modules.size() != size; size /= sizeof(HMODULE)) @@ -1795,14 +1804,7 @@ static void signal_handler(int /*sig*/, siginfo_t* info, void* uct) noexcept std::string msg = fmt::format("Segfault %s location %p at %p.\n", cause, info->si_addr, RIP(context)); - if (thread_ctrl::get_current()) - { - fmt::append(msg, "Emu Thread Name: '%s'.\n", thread_ctrl::get_name()); - } - - // TODO: Report full thread name if not an emu thread - - fmt::append(msg, "Thread id = %s.\n", std::this_thread::get_id()); + append_thread_name(msg); if (IsDebuggerPresent()) { @@ -2542,8 +2544,7 @@ void thread_base::exec() #endif } - // Assume main thread - report_fatal_error(std::string(reason)); + report_fatal_error(reason); } void thread_ctrl::detect_cpu_layout() diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index ed0029530a..989d19c3f0 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -88,7 +88,7 @@ atomic_t g_progr_ptotal{0}; atomic_t g_progr_pdone{0}; // Report error and call std::abort(), defined in main.cpp -[[noreturn]] void report_fatal_error(const std::string&); +[[noreturn]] void report_fatal_error(std::string_view); namespace { diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index 707d93ceb5..3cd1704caf 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -61,6 +61,8 @@ static atomic_t s_headless = false; static atomic_t s_no_gui = false; static atomic_t s_argv0; +extern thread_local std::string(*g_tls_log_prefix)(); + #ifndef _WIN32 extern char **environ; #endif @@ -68,15 +70,29 @@ extern char **environ; LOG_CHANNEL(sys_log, "SYS"); LOG_CHANNEL(q_debug, "QDEBUG"); -[[noreturn]] extern void report_fatal_error(const std::string& text) +[[noreturn]] extern void report_fatal_error(std::string_view _text) { + std::string buf; + + // Check if thread id is in string + if (_text.find("\nThread id = "sv) == umax) + { + // Copy only when needed + buf = std::string(_text); + + // Always print thread id + fmt::append(buf, "\nThread id = %s.", std::this_thread::get_id()); + } + + const std::string_view text = buf.empty() ? _text : buf; + if (s_headless) { #ifdef _WIN32 if (AttachConsole(ATTACH_PARENT_PROCESS) || AllocConsole()) [[maybe_unused]] const auto con_out = freopen("conout$", "w", stderr); #endif - fprintf(stderr, "RPCS3: %s\n", text.c_str()); + std::fprintf(stderr, "RPCS3: %.*s\n", static_cast(text.size()), text.data()); std::abort(); } @@ -93,10 +109,10 @@ LOG_CHANNEL(q_debug, "QDEBUG"); } else { - fprintf(stderr, "RPCS3: %s\n", text.c_str()); + std::fprintf(stderr, "RPCS3: %.*s\n", static_cast(text.size()), text.data()); } - auto show_report = [](const std::string& text) + auto show_report = [](std::string_view text) { fatal_error_dialog dlg(text); dlg.exec(); @@ -154,7 +170,7 @@ LOG_CHANNEL(q_debug, "QDEBUG"); } else { - fprintf(stderr, "posix_spawn() failed: %d\n", ret); + std::fprintf(stderr, "posix_spawn() failed: %d\n", ret); } #endif std::abort(); diff --git a/rpcs3/rpcs3qt/fatal_error_dialog.cpp b/rpcs3/rpcs3qt/fatal_error_dialog.cpp index becf5cfaed..497e634497 100644 --- a/rpcs3/rpcs3qt/fatal_error_dialog.cpp +++ b/rpcs3/rpcs3qt/fatal_error_dialog.cpp @@ -3,9 +3,7 @@ #include #include -#include - -fatal_error_dialog::fatal_error_dialog(const std::string& text) : QMessageBox() +fatal_error_dialog::fatal_error_dialog(std::string_view text) : QMessageBox() { setWindowTitle(tr("RPCS3: Fatal Error")); setIcon(QMessageBox::Icon::Critical); @@ -18,7 +16,7 @@ fatal_error_dialog::fatal_error_dialog(const std::string& text) : QMessageBox() %3

)") - .arg(Qt::convertFromPlainText(QString::fromStdString(text))) + .arg(Qt::convertFromPlainText(QString::fromUtf8(text.data(), text.size()))) .arg(tr("HOW TO REPORT ERRORS:")) .arg(tr("Please, don't send incorrect reports. Thanks for understanding."))); layout()->setSizeConstraint(QLayout::SetFixedSize); diff --git a/rpcs3/rpcs3qt/fatal_error_dialog.h b/rpcs3/rpcs3qt/fatal_error_dialog.h index 15c5bbdc23..f7b4586c4e 100644 --- a/rpcs3/rpcs3qt/fatal_error_dialog.h +++ b/rpcs3/rpcs3qt/fatal_error_dialog.h @@ -2,12 +2,12 @@ #include -#include +#include class fatal_error_dialog : public QMessageBox { Q_OBJECT public: - fatal_error_dialog(const std::string& text); + fatal_error_dialog(std::string_view text); }; diff --git a/rpcs3/util/logs.cpp b/rpcs3/util/logs.cpp index 72e83b5761..73ce17554c 100644 --- a/rpcs3/util/logs.cpp +++ b/rpcs3/util/logs.cpp @@ -2,6 +2,7 @@ #include "Utilities/File.h" #include "Utilities/mutex.h" #include "Utilities/Thread.h" +#include "Utilities/StrFmt.h" #include #include #include @@ -25,13 +26,18 @@ using namespace std::literals::chrono_literals; #include -static std::string empty_string() +static std::string default_string() { - return {}; + if (thread_ctrl::is_main()) + { + return {}; + } + + return fmt::format("TID: %s", std::this_thread::get_id()); } // Thread-specific log prefix provider -thread_local std::string(*g_tls_log_prefix)() = &empty_string; +thread_local std::string(*g_tls_log_prefix)() = &default_string; // Another thread-specific callback thread_local void(*g_tls_log_control)(const char* fmt, u64 progress) = [](const char*, u64){};