From 55c5f756d80cb762fa21054c7460359424428668 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 17 Apr 2015 09:30:22 -0400 Subject: [PATCH 1/4] Attempt to fix Windows TLS memory leak. --- src/global.c | 18 +++++++++++++----- src/global.h | 2 ++ src/win32/pthread.c | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/global.c b/src/global.c index 1f3432d09..3c97e62e6 100644 --- a/src/global.c +++ b/src/global.c @@ -270,13 +270,21 @@ git_global_st *git__global_state(void) return ptr; } +void git__free_thread_global_state(void) +{ + void *ptr = TlsGetValue(_tls_index); + if (!ptr) + return; + + git__global_state_cleanup(ptr); + git__free(ptr); + TlsSetValue(_tls_index, NULL); +} + BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) { - if (reason == DLL_THREAD_DETACH) { - void *ptr = TlsGetValue(_tls_index); - git__global_state_cleanup(ptr); - git__free(ptr); - } + if (reason == DLL_THREAD_DETACH) + git__free_thread_global_state(); return TRUE; } diff --git a/src/global.h b/src/global.h index a89a8d6ab..9d763b0c2 100644 --- a/src/global.h +++ b/src/global.h @@ -32,4 +32,6 @@ typedef void (*git_global_shutdown_fn)(void); extern void git__on_shutdown(git_global_shutdown_fn callback); +extern void git__free_thread_global_state(void); + #endif diff --git a/src/win32/pthread.c b/src/win32/pthread.c index ec45ecbe5..a6465d47f 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -20,6 +20,8 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter) thread->result = thread->proc(thread->param); + git__free_thread_global_state(); + return CLEAN_THREAD_EXIT; } From f5ffb40e2b7f0ba1a0d6494037cfa2c24dd30c47 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 17 Apr 2015 09:58:09 -0400 Subject: [PATCH 2/4] Also fix leak of TLS data on main thread. --- src/global.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/global.c b/src/global.c index 3c97e62e6..0772bb0af 100644 --- a/src/global.c +++ b/src/global.c @@ -223,13 +223,10 @@ int git_libgit2_init(void) static void synchronized_threads_shutdown(void) { - void *ptr; - /* Shut down any subsystems that have global state */ git__shutdown(); - ptr = TlsGetValue(_tls_index); - git__global_state_cleanup(ptr); + git__free_thread_global_state(); TlsFree(_tls_index); git_mutex_free(&git__mwindow_mutex); From d3fb7d93a6e2ead0506e17152030ab7dfdb1ac41 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Fri, 17 Apr 2015 10:04:01 -0400 Subject: [PATCH 3/4] Remove DllMain now that TLS data freed by threads --- src/global.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/global.c b/src/global.c index 0772bb0af..b5e4b5d00 100644 --- a/src/global.c +++ b/src/global.c @@ -278,14 +278,6 @@ void git__free_thread_global_state(void) TlsSetValue(_tls_index, NULL); } -BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) -{ - if (reason == DLL_THREAD_DETACH) - git__free_thread_global_state(); - - return TRUE; -} - #elif defined(GIT_THREADS) && defined(_POSIX_THREADS) static pthread_key_t _tls_key; From 06c985d8647a254000ed172fd888cc853a2c91dd Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Sat, 18 Apr 2015 09:07:48 -0400 Subject: [PATCH 4/4] Rename routine to free TLS data --- src/global.c | 9 +++++++-- src/global.h | 2 +- src/win32/pthread.c | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/global.c b/src/global.c index b5e4b5d00..f267fbd24 100644 --- a/src/global.c +++ b/src/global.c @@ -226,7 +226,7 @@ static void synchronized_threads_shutdown(void) /* Shut down any subsystems that have global state */ git__shutdown(); - git__free_thread_global_state(); + git__free_tls_data(); TlsFree(_tls_index); git_mutex_free(&git__mwindow_mutex); @@ -267,7 +267,12 @@ git_global_st *git__global_state(void) return ptr; } -void git__free_thread_global_state(void) +/** + * Free the TLS data associated with this thread. + * This should only be used by the thread as it + * is exiting. + */ +void git__free_tls_data(void) { void *ptr = TlsGetValue(_tls_index); if (!ptr) diff --git a/src/global.h b/src/global.h index 9d763b0c2..f56bec46c 100644 --- a/src/global.h +++ b/src/global.h @@ -32,6 +32,6 @@ typedef void (*git_global_shutdown_fn)(void); extern void git__on_shutdown(git_global_shutdown_fn callback); -extern void git__free_thread_global_state(void); +extern void git__free_tls_data(void); #endif diff --git a/src/win32/pthread.c b/src/win32/pthread.c index a6465d47f..a1cc18932 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -20,7 +20,7 @@ static DWORD WINAPI git_win32__threadproc(LPVOID lpParameter) thread->result = thread->proc(thread->param); - git__free_thread_global_state(); + git__free_tls_data(); return CLEAN_THREAD_EXIT; }