Skip to content

Commit b3abf51

Browse files
committed
Make logger thread-safe and robust
1 parent 5c32b5e commit b3abf51

2 files changed

Lines changed: 59 additions & 7 deletions

File tree

src/Logger.cpp

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,36 @@
11
#include "Logger.h"
22

33
#include <cstdio>
4+
#include <mutex>
5+
#include <shared_mutex>
46

57
#ifndef WIN32_LEAN_AND_MEAN
68
#define WIN32_LEAN_AND_MEAN
79
#endif
810
#include <Windows.h>
911

12+
#if defined(_MSC_VER)
13+
#define BML_SAFE_FPRINTF(stream, ...) ::fprintf_s(stream, __VA_ARGS__)
14+
#define BML_SAFE_VFPRINTF(stream, format, args) ::vfprintf_s(stream, format, args)
15+
#else
16+
#define BML_SAFE_FPRINTF(stream, ...) std::fprintf(stream, __VA_ARGS__)
17+
#define BML_SAFE_VFPRINTF(stream, format, args) std::vfprintf(stream, format, args)
18+
#endif
19+
1020
#include "ModContext.h"
1121

22+
static std::shared_mutex g_DefaultLoggerMutex;
23+
static std::mutex g_LogWriteMutex;
24+
1225
Logger *Logger::m_DefaultLogger = nullptr;
1326

1427
Logger *Logger::GetDefault() {
28+
std::shared_lock lock(g_DefaultLoggerMutex);
1529
return m_DefaultLogger;
1630
}
1731

1832
void Logger::SetDefault(Logger *logger) {
33+
std::unique_lock lock(g_DefaultLoggerMutex);
1934
m_DefaultLogger = logger;
2035
}
2136

@@ -43,6 +58,9 @@ void Logger::Error(const char *fmt, ...) {
4358
}
4459

4560
void Logger::Log(const char *level, const char *fmt, va_list args) {
61+
if (!level || !fmt)
62+
return;
63+
4664
SYSTEMTIME sys;
4765
GetLocalTime(&sys);
4866

@@ -53,12 +71,31 @@ void Logger::Log(const char *level, const char *fmt, va_list args) {
5371
BML_GetModContext()->GetLogFile()
5472
};
5573

56-
for (FILE *file: outFiles) {
57-
fprintf(file, "[%02d/%02d/%d %02d:%02d:%02d.%03d] ", sys.wMonth, sys.wDay,
58-
sys.wYear, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds);
59-
fprintf(file, "[%s/%s]: ", m_ModName, level);
60-
vfprintf(file, fmt, args);
74+
std::lock_guard lock(g_LogWriteMutex);
75+
for (FILE *file : outFiles) {
76+
if (!file)
77+
continue;
78+
79+
BML_SAFE_FPRINTF(file,
80+
"[%02d/%02d/%d %02d:%02d:%02d.%03d] ",
81+
sys.wMonth,
82+
sys.wDay,
83+
sys.wYear,
84+
sys.wHour,
85+
sys.wMinute,
86+
sys.wSecond,
87+
sys.wMilliseconds);
88+
BML_SAFE_FPRINTF(file, "[%s/%s]: ", m_ModName, level);
89+
90+
va_list argsCopy;
91+
va_copy(argsCopy, args);
92+
BML_SAFE_VFPRINTF(file, fmt, argsCopy);
93+
va_end(argsCopy);
94+
6195
fputc('\n', file);
6296
fflush(file);
6397
}
64-
}
98+
}
99+
100+
#undef BML_SAFE_FPRINTF
101+
#undef BML_SAFE_VFPRINTF

src/ModContext.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,15 +1001,27 @@ void ModContext::InitDirectories() {
10011001

10021002
void ModContext::InitLogger() {
10031003
std::wstring logfilePath = m_LoaderDir + L"\\ModLoader.log";
1004+
m_Logfile = nullptr;
1005+
#if defined(_MSC_VER)
1006+
if (_wfopen_s(&m_Logfile, logfilePath.c_str(), L"w") != 0) {
1007+
m_Logfile = nullptr;
1008+
}
1009+
#else
10041010
m_Logfile = _wfopen(logfilePath.c_str(), L"w");
1011+
#endif
10051012
auto *logger = new Logger("ModLoader");
10061013
Logger::SetDefault(logger);
10071014
m_Logger = logger;
10081015

10091016
#ifdef _DEBUG
10101017
AllocConsole();
1018+
#if defined(_MSC_VER)
1019+
FILE *console = nullptr;
1020+
freopen_s(&console, "CONOUT$", "w", stdout);
1021+
#else
10111022
freopen("CONOUT$", "w", stdout);
10121023
#endif
1024+
#endif
10131025
}
10141026

10151027
void ModContext::ShutdownLogger() {
@@ -1019,7 +1031,10 @@ void ModContext::ShutdownLogger() {
10191031

10201032
Logger::SetDefault(nullptr);
10211033
delete m_Logger;
1022-
fclose(m_Logfile);
1034+
if (m_Logfile) {
1035+
fclose(m_Logfile);
1036+
m_Logfile = nullptr;
1037+
}
10231038
}
10241039

10251040
extern bool HookObjectLoad();

0 commit comments

Comments
 (0)