Use async logging while streaming only

The benefits of reliable output outweigh performance concerns during non-streaming activities.
This commit is contained in:
Cameron Gutman
2025-10-25 00:18:34 -05:00
parent b1232e0ed4
commit bd6235efba
4 changed files with 49 additions and 2 deletions

View File

@@ -60,9 +60,16 @@
// Log to console for debug Mac builds
#endif
// StreamUtils::setAsyncLogging() exposes control of this to the Session
// class to enable async logging once the stream has started.
//
// FIXME: Clean this up
QAtomicInt g_AsyncLoggingEnabled;
static QElapsedTimer s_LoggerTime;
static QTextStream s_LoggerStream(stderr);
static QThreadPool s_LoggerThread;
static QMutex s_SyncLoggerMutex;
static bool s_SuppressVerboseOutput;
static QRegularExpression k_RikeyRegex("&rikey=\\w+");
static QRegularExpression k_RikeyIdRegex("&rikeyid=[\\d-]+");
@@ -127,8 +134,16 @@ void logToLoggerStream(QString& message)
}
#endif
if (g_AsyncLoggingEnabled) {
// Queue the log message to be written asynchronously
s_LoggerThread.start(new LoggerTask(message));
}
else {
// QTextStream is not thread-safe, so we must lock
QMutexLocker locker(&s_SyncLoggerMutex);
s_LoggerStream << message;
s_LoggerStream.flush();
}
}
void sdlLogToDiskHandler(void*, int category, SDL_LogPriority priority, const char* message)
@@ -298,6 +313,11 @@ LONG WINAPI UnhandledExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
qCritical() << "Unhandled exception! Failed to open dump file:" << qDmpFileName << "with error" << GetLastError();
}
// Sleep for a moment to allow the logging thread to finish up before crashing
if (g_AsyncLoggingEnabled) {
Sleep(500);
}
// Let the program crash and WER collect a dump
return EXCEPTION_CONTINUE_SEARCH;
}
@@ -826,6 +846,9 @@ int main(int argc, char *argv[])
av_log_set_callback(av_log_default_callback);
#endif
// We should not be in async logging mode anymore
Q_ASSERT(g_AsyncLoggingEnabled == 0);
// Wait for pending log messages to be printed
s_LoggerThread.waitForDone();

View File

@@ -2014,6 +2014,9 @@ void Session::execInternal()
// Toggle the stats overlay if requested by the user
m_OverlayManager.setOverlayState(Overlay::OverlayDebug, m_Preferences->showPerformanceOverlay);
// Switch to async logging mode when we enter the SDL loop
StreamUtils::enterAsyncLoggingMode();
// Hijack this thread to be the SDL main thread. We have to do this
// because we want to suspend all Qt processing until the stream is over.
SDL_Event event;
@@ -2363,6 +2366,9 @@ void Session::execInternal()
}
DispatchDeferredCleanup:
// Switch back to synchronous logging mode
StreamUtils::exitAsyncLoggingMode();
// Uncapture the mouse and hide the window immediately,
// so we can return to the Qt GUI ASAP.
m_InputHandler->setCaptureActive(false);

View File

@@ -417,3 +417,15 @@ int StreamUtils::getDrmFd(bool preferRenderNode)
return -1;
}
extern QAtomicInt g_AsyncLoggingEnabled;
void StreamUtils::enterAsyncLoggingMode()
{
g_AsyncLoggingEnabled.ref();
}
void StreamUtils::exitAsyncLoggingMode()
{
g_AsyncLoggingEnabled.deref();
}

View File

@@ -31,4 +31,10 @@ public:
static
int getDrmFd(bool preferRenderNode);
static
void enterAsyncLoggingMode();
static
void exitAsyncLoggingMode();
};