common: Intentionally leak logger instance to fix hanging on Windows (#22273)
* Changed to leak logger singleton to prevent hanging on Windows * Fix comment * Stopped using static vector Using std::vector will cause g_col to be released before the logger thread exits, causing the logger thread to touch freed memory causing a crash * Change so all logs are output before exit * Added debug logging * added more logging * Added logging * Explicitly free logger to avoid hanging on Win * Reverted to leak logger instance again * Removed debug log and fixed comment * Fixed comment --------- Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
This commit is contained in:
+11
-8
@@ -49,7 +49,7 @@ enum common_log_col : int {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// disable colors by default
|
// disable colors by default
|
||||||
static std::vector<const char *> g_col = {
|
static const char* g_col[] = {
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
@@ -247,7 +247,6 @@ public:
|
|||||||
|
|
||||||
entries = std::move(new_entries);
|
entries = std::move(new_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +264,6 @@ public:
|
|||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mtx);
|
std::unique_lock<std::mutex> lock(mtx);
|
||||||
cv.wait(lock, [this]() { return head != tail; });
|
cv.wait(lock, [this]() { return head != tail; });
|
||||||
|
|
||||||
cur = entries[head];
|
cur = entries[head];
|
||||||
|
|
||||||
head = (head + 1) % entries.size();
|
head = (head + 1) % entries.size();
|
||||||
@@ -301,7 +299,6 @@ public:
|
|||||||
|
|
||||||
tail = (tail + 1) % entries.size();
|
tail = (tail + 1) % entries.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +335,7 @@ public:
|
|||||||
g_col[COMMON_LOG_COL_CYAN] = LOG_COL_CYAN;
|
g_col[COMMON_LOG_COL_CYAN] = LOG_COL_CYAN;
|
||||||
g_col[COMMON_LOG_COL_WHITE] = LOG_COL_WHITE;
|
g_col[COMMON_LOG_COL_WHITE] = LOG_COL_WHITE;
|
||||||
} else {
|
} else {
|
||||||
for (size_t i = 0; i < g_col.size(); i++) {
|
for (size_t i = 0; i < std::size(g_col); i++) {
|
||||||
g_col[i] = "";
|
g_col[i] = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,14 +365,20 @@ struct common_log * common_log_init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct common_log * common_log_main() {
|
struct common_log * common_log_main() {
|
||||||
static struct common_log log;
|
// We intentionally leak (i.e. do not delete) the logger singleton because
|
||||||
|
// common_log destructor called at DLL teardown phase will cause hanging on Windows.
|
||||||
|
// OS will release resources anyway so it should not be a significant issue,
|
||||||
|
// though this design may cause logs to be lost if not flushed before the program exits.
|
||||||
|
// Refer to https://github.com/ggml-org/llama.cpp/issues/22142 for details.
|
||||||
|
static struct common_log * log;
|
||||||
static std::once_flag init_flag;
|
static std::once_flag init_flag;
|
||||||
std::call_once(init_flag, [&]() {
|
std::call_once(init_flag, [&]() {
|
||||||
|
log = new common_log;
|
||||||
// Set default to auto-detect colors
|
// Set default to auto-detect colors
|
||||||
log.set_colors(tty_can_use_colors());
|
log->set_colors(tty_can_use_colors());
|
||||||
});
|
});
|
||||||
|
|
||||||
return &log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
||||||
void common_log_pause(struct common_log * log) {
|
void common_log_pause(struct common_log * log) {
|
||||||
|
|||||||
+5
-1
@@ -49,7 +49,11 @@ void common_log_default_callback(enum ggml_log_level level, const char * text, v
|
|||||||
struct common_log;
|
struct common_log;
|
||||||
|
|
||||||
struct common_log * common_log_init();
|
struct common_log * common_log_init();
|
||||||
struct common_log * common_log_main(); // singleton, automatically destroys itself on exit
|
|
||||||
|
// Singleton, intentionally leaked to avoid Windows teardown hangs.
|
||||||
|
// Call common_log_flush() before exit if you want to ensure all logs are flushed.
|
||||||
|
struct common_log * common_log_main();
|
||||||
|
|
||||||
void common_log_pause (struct common_log * log); // pause the worker thread, not thread-safe
|
void common_log_pause (struct common_log * log); // pause the worker thread, not thread-safe
|
||||||
void common_log_resume(struct common_log * log); // resume the worker thread, not thread-safe
|
void common_log_resume(struct common_log * log); // resume the worker thread, not thread-safe
|
||||||
void common_log_free (struct common_log * log);
|
void common_log_free (struct common_log * log);
|
||||||
|
|||||||
@@ -35,5 +35,9 @@ int main() {
|
|||||||
threads[i].join();
|
threads[i].join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
common_log_flush(common_log_main());
|
||||||
|
// We explicitly free the logger singleton to avoid hanging on Windows
|
||||||
|
// related to timing issues of thread startup and DLL teardown
|
||||||
|
common_log_free(common_log_main());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user