Skip to content

Commit 7b95ea5

Browse files
rillomasggerganov
andauthored
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>
1 parent bdc9c74 commit 7b95ea5

3 files changed

Lines changed: 20 additions & 9 deletions

File tree

common/log.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ enum common_log_col : int {
4949
};
5050

5151
// disable colors by default
52-
static std::vector<const char *> g_col = {
52+
static const char* g_col[] = {
5353
"",
5454
"",
5555
"",
@@ -247,7 +247,6 @@ struct common_log {
247247

248248
entries = std::move(new_entries);
249249
}
250-
251250
cv.notify_one();
252251
}
253252

@@ -265,7 +264,6 @@ struct common_log {
265264
{
266265
std::unique_lock<std::mutex> lock(mtx);
267266
cv.wait(lock, [this]() { return head != tail; });
268-
269267
cur = entries[head];
270268

271269
head = (head + 1) % entries.size();
@@ -301,7 +299,6 @@ struct common_log {
301299

302300
tail = (tail + 1) % entries.size();
303301
}
304-
305302
cv.notify_one();
306303
}
307304

@@ -338,7 +335,7 @@ struct common_log {
338335
g_col[COMMON_LOG_COL_CYAN] = LOG_COL_CYAN;
339336
g_col[COMMON_LOG_COL_WHITE] = LOG_COL_WHITE;
340337
} else {
341-
for (size_t i = 0; i < g_col.size(); i++) {
338+
for (size_t i = 0; i < std::size(g_col); i++) {
342339
g_col[i] = "";
343340
}
344341
}
@@ -368,14 +365,20 @@ struct common_log * common_log_init() {
368365
}
369366

370367
struct common_log * common_log_main() {
371-
static struct common_log log;
368+
// We intentionally leak (i.e. do not delete) the logger singleton because
369+
// common_log destructor called at DLL teardown phase will cause hanging on Windows.
370+
// OS will release resources anyway so it should not be a significant issue,
371+
// though this design may cause logs to be lost if not flushed before the program exits.
372+
// Refer to https://github.com/ggml-org/llama.cpp/issues/22142 for details.
373+
static struct common_log * log;
372374
static std::once_flag init_flag;
373375
std::call_once(init_flag, [&]() {
376+
log = new common_log;
374377
// Set default to auto-detect colors
375-
log.set_colors(tty_can_use_colors());
378+
log->set_colors(tty_can_use_colors());
376379
});
377380

378-
return &log;
381+
return log;
379382
}
380383

381384
void common_log_pause(struct common_log * log) {

common/log.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ void common_log_default_callback(enum ggml_log_level level, const char * text, v
4949
struct common_log;
5050

5151
struct common_log * common_log_init();
52-
struct common_log * common_log_main(); // singleton, automatically destroys itself on exit
52+
53+
// Singleton, intentionally leaked to avoid Windows teardown hangs.
54+
// Call common_log_flush() before exit if you want to ensure all logs are flushed.
55+
struct common_log * common_log_main();
56+
5357
void common_log_pause (struct common_log * log); // pause the worker thread, not thread-safe
5458
void common_log_resume(struct common_log * log); // resume the worker thread, not thread-safe
5559
void common_log_free (struct common_log * log);

tests/test-log.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,9 @@ int main() {
3535
threads[i].join();
3636
}
3737

38+
common_log_flush(common_log_main());
39+
// We explicitly free the logger singleton to avoid hanging on Windows
40+
// related to timing issues of thread startup and DLL teardown
41+
common_log_free(common_log_main());
3842
return 0;
3943
}

0 commit comments

Comments
 (0)