diff --git a/Utilities/Log.cpp b/Utilities/Log.cpp index 32f3c92669..2ed352d98f 100644 --- a/Utilities/Log.cpp +++ b/Utilities/Log.cpp @@ -61,13 +61,7 @@ namespace logs struct file_listener : public file_writer, public listener { - file_listener(const std::string& name) - : file_writer(name) - , listener() - { - const std::string& start = fmt::format("\xEF\xBB\xBF" "RPCS3 v%s\n%s\n", rpcs3::version.to_string(), utils::get_system_info()); - file_writer::log(start.data(), start.size()); - } + file_listener(const std::string& name); // Encode level, current thread name, channel name and write log message virtual void log(u64 stamp, const message& msg, const std::string& prefix, const std::string& text) override; @@ -138,12 +132,26 @@ namespace logs } }; + struct stored_message + { + message m; + u64 stamp; + std::string prefix; + std::string text; + }; + // Channel registry mutex semaphore<> g_mutex; // Channel registry std::unordered_map g_channels; + // Messages for delayed listener initialization + std::vector g_messages; + + // Must be set to true in main() + atomic_t g_init{false}; + void reset() { semaphore_lock lock(g_mutex); @@ -160,6 +168,17 @@ namespace logs g_channels[ch_name].set_level(value); } + + // Must be called in main() to stop accumulating messages in g_messages + void set_init() + { + if (!g_init) + { + semaphore_lock lock(g_mutex); + g_messages.clear(); + g_init = true; + } + } } logs::listener::~listener() @@ -171,11 +190,19 @@ void logs::listener::add(logs::listener* _new) // Get first (main) listener listener* lis = get_logger(); + semaphore_lock lock(g_mutex); + // Install new listener at the end of linked list while (lis->m_next || !lis->m_next.compare_and_swap_test(nullptr, _new)) { lis = lis->m_next; } + + // Send initial messages + for (const auto& msg : g_messages) + { + _new->log(msg.stamp, msg.m, msg.prefix, msg.text); + } } void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u64* args) @@ -214,6 +241,23 @@ void logs::message::broadcast(const char* fmt, const fmt_type_info* sup, const u // Get first (main) listener listener* lis = get_logger(); + + if (!g_init) + { + semaphore_lock lock(g_mutex); + + if (!g_init) + { + while (lis) + { + lis->log(stamp, *this, prefix, text); + lis = lis->m_next; + } + + // Store message additionally + g_messages.emplace_back(stored_message{*this, stamp, std::move(prefix), std::move(text)}); + } + } // Send message to all listeners while (lis) @@ -245,6 +289,24 @@ void logs::file_writer::log(const char* text, std::size_t size) m_file.write(text, size); } +logs::file_listener::file_listener(const std::string& name) + : file_writer(name) + , listener() +{ + // Write UTF-8 BOM + file_writer::log("\xEF\xBB\xBF", 3); + + // Write initial message + stored_message ver; + ver.m.ch = nullptr; + ver.m.sev = level::always; + ver.stamp = 0; + ver.text = fmt::format("RPCS3 v%s\n%s", rpcs3::version.to_string(), utils::get_system_info()); + file_writer::log(ver.text.data(), ver.text.size()); + file_writer::log("\n", 1); + g_messages.emplace_back(std::move(ver)); +} + void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::string& prefix, const std::string& _text) { std::string text; text.reserve(prefix.size() + _text.size() + 200); @@ -276,7 +338,7 @@ void logs::file_listener::log(u64 stamp, const logs::message& msg, const std::st text += "} "; } - if ('\0' != *msg.ch->name) + if (msg.ch && '\0' != *msg.ch->name) { text += msg.ch->name; text += msg.sev == level::todo ? " TODO: " : ": "; diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index 3b54d81a4e..513f437b62 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -13,8 +13,15 @@ inline std::string sstr(const QString& _in) { return _in.toUtf8().toStdString(); } +namespace logs +{ + void set_init(); +} + int main(int argc, char** argv) { + logs::set_init(); + #ifdef _WIN32 SetProcessDPIAware(); WSADATA wsa_data; diff --git a/rpcs3/rpcs3qt/log_frame.cpp b/rpcs3/rpcs3qt/log_frame.cpp index cc9c3f20ad..b5acbe909a 100644 --- a/rpcs3/rpcs3qt/log_frame.cpp +++ b/rpcs3/rpcs3qt/log_frame.cpp @@ -12,7 +12,7 @@ constexpr auto qstr = QString::fromStdString; struct gui_listener : logs::listener { - atomic_t enabled{}; + atomic_t enabled{logs::level::_uninit}; struct packet { @@ -35,13 +35,9 @@ struct gui_listener : logs::listener gui_listener() : logs::listener() + , last(new packet) + , read(+last) { - // Initialize packets - read = new packet; - last = new packet; - read->next = last.load(); - last->msg = fmt::format("RPCS3 v%s\n%s\n", rpcs3::version.to_string(), utils::get_system_info()); - // Self-registration logs::listener::add(this); } @@ -67,7 +63,7 @@ struct gui_listener : logs::listener _new->msg += "} "; } - if ('\0' != *msg.ch->name) + if (msg.ch && '\0' != *msg.ch->name) { _new->msg += msg.ch->name; _new->msg += msg.sev == logs::level::todo ? " TODO: " : ": ";