Commit aaf42c8df75a78344e3e231260a935d2e034d8eb

Edward Thomson 2015-04-21T18:21:59

Merge pull request #3051 from jeffhostetler/jeffhostetler/memleak_windows_tls_data Attempt to fix Windows TLS memory leak.

diff --git a/src/global.c b/src/global.c
index 1f3432d..f267fbd 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_tls_data();
 
 	TlsFree(_tls_index);
 	git_mutex_free(&git__mwindow_mutex);
@@ -270,15 +267,20 @@ git_global_st *git__global_state(void)
 	return ptr;
 }
 
-BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
+/**
+ * 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)
 {
-	if (reason == DLL_THREAD_DETACH) {
-		void *ptr = TlsGetValue(_tls_index);
-		git__global_state_cleanup(ptr);
-		git__free(ptr);
-	}
+	void *ptr = TlsGetValue(_tls_index);
+	if (!ptr)
+		return;
 
-	return TRUE;
+	git__global_state_cleanup(ptr);
+	git__free(ptr);
+	TlsSetValue(_tls_index, NULL);
 }
 
 #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
diff --git a/src/global.h b/src/global.h
index a89a8d6..f56bec4 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_tls_data(void);
+
 #endif
diff --git a/src/win32/pthread.c b/src/win32/pthread.c
index ec45ecb..a1cc189 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_tls_data();
+
 	return CLEAN_THREAD_EXIT;
 }