Commit a3aa5f4d by Russell Belfer

Add simple global shutdown hooks

Increasingly there are a number of components that want to do some
cleanup at global shutdown time (at least if there are not going
to be memory leaks).  This creates a very simple system of shutdown
hooks that will be invoked by git_threads_shutdown.  Right now, the
maximum number of hooks is hardcoded, but since adding a hook is
not a public API, it should be fine and I thought it was better to
start off with really simple code.
parent e7d0ced2
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#include "common.h" #include "common.h"
#include "fileops.h" #include "fileops.h"
#include "global.h"
#include <ctype.h> #include <ctype.h>
#if GIT_WIN32 #if GIT_WIN32
#include "win32/findfile.h" #include "win32/findfile.h"
...@@ -635,6 +636,13 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = { ...@@ -635,6 +636,13 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = {
git_futils_guess_xdg_dirs, git_futils_guess_xdg_dirs,
}; };
static void git_futils_dirs_global_shutdown(void)
{
int i;
for (i = 0; i < GIT_FUTILS_DIR__MAX; ++i)
git_buf_free(&git_futils__dirs[i]);
}
int git_futils_dirs_global_init(void) int git_futils_dirs_global_init(void)
{ {
git_futils_dir_t i; git_futils_dir_t i;
...@@ -644,6 +652,8 @@ int git_futils_dirs_global_init(void) ...@@ -644,6 +652,8 @@ int git_futils_dirs_global_init(void)
for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++) for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++)
error = git_futils_dirs_get(&path, i); error = git_futils_dirs_get(&path, i);
git__on_shutdown(git_futils_dirs_global_shutdown);
return error; return error;
} }
...@@ -726,13 +736,6 @@ int git_futils_dirs_set(git_futils_dir_t which, const char *search_path) ...@@ -726,13 +736,6 @@ int git_futils_dirs_set(git_futils_dir_t which, const char *search_path)
return git_buf_oom(&git_futils__dirs[which]) ? -1 : 0; return git_buf_oom(&git_futils__dirs[which]) ? -1 : 0;
} }
void git_futils_dirs_free(void)
{
int i;
for (i = 0; i < GIT_FUTILS_DIR__MAX; ++i)
git_buf_free(&git_futils__dirs[i]);
}
static int git_futils_find_in_dirlist( static int git_futils_find_in_dirlist(
git_buf *path, const char *name, git_futils_dir_t which, const char *label) git_buf *path, const char *name, git_futils_dir_t which, const char *label)
{ {
......
...@@ -354,11 +354,6 @@ extern int git_futils_dirs_get_str( ...@@ -354,11 +354,6 @@ extern int git_futils_dirs_get_str(
extern int git_futils_dirs_set(git_futils_dir_t which, const char *paths); extern int git_futils_dirs_set(git_futils_dir_t which, const char *paths);
/** /**
* Release / reset all search paths
*/
extern void git_futils_dirs_free(void);
/**
* Create a "fake" symlink (text file containing the target path). * Create a "fake" symlink (text file containing the target path).
* *
* @param new symlink file to be created * @param new symlink file to be created
......
...@@ -14,6 +14,28 @@ ...@@ -14,6 +14,28 @@
git_mutex git__mwindow_mutex; git_mutex git__mwindow_mutex;
#define MAX_SHUTDOWN_CB 8
git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
git_atomic git__n_shutdown_callbacks;
void git__on_shutdown(git_global_shutdown_fn callback)
{
int count = git_atomic_inc(&git__n_shutdown_callbacks);
assert(count <= MAX_SHUTDOWN_CB);
git__shutdown_callbacks[count - 1] = callback;
}
static void git__shutdown(void)
{
int pos;
while ((pos = git_atomic_dec(&git__n_shutdown_callbacks)) >= 0) {
if (git__shutdown_callbacks[pos])
git__shutdown_callbacks[pos]();
}
}
/** /**
* Handle the global state with TLS * Handle the global state with TLS
* *
...@@ -79,9 +101,7 @@ int git_threads_init(void) ...@@ -79,9 +101,7 @@ int git_threads_init(void)
void git_threads_shutdown(void) void git_threads_shutdown(void)
{ {
/* Shut down any subsystems that have global state */ /* Shut down any subsystems that have global state */
win32_pthread_shutdown(); git__shutdown();
git_futils_dirs_free();
git_hash_global_shutdown();
TlsFree(_tls_index); TlsFree(_tls_index);
_tls_init = 0; _tls_init = 0;
...@@ -140,6 +160,9 @@ int git_threads_init(void) ...@@ -140,6 +160,9 @@ int git_threads_init(void)
void git_threads_shutdown(void) void git_threads_shutdown(void)
{ {
/* Shut down any subsystems that have global state */
git__shutdown();
if (_tls_init) { if (_tls_init) {
void *ptr = pthread_getspecific(_tls_key); void *ptr = pthread_getspecific(_tls_key);
pthread_setspecific(_tls_key, NULL); pthread_setspecific(_tls_key, NULL);
...@@ -149,10 +172,6 @@ void git_threads_shutdown(void) ...@@ -149,10 +172,6 @@ void git_threads_shutdown(void)
pthread_key_delete(_tls_key); pthread_key_delete(_tls_key);
_tls_init = 0; _tls_init = 0;
git_mutex_free(&git__mwindow_mutex); git_mutex_free(&git__mwindow_mutex);
/* Shut down any subsystems that have global state */
git_hash_global_shutdown();
git_futils_dirs_free();
} }
git_global_st *git__global_state(void) git_global_st *git__global_state(void)
...@@ -179,15 +198,14 @@ static git_global_st __state; ...@@ -179,15 +198,14 @@ static git_global_st __state;
int git_threads_init(void) int git_threads_init(void)
{ {
/* noop */ /* noop */
return 0; return 0;
} }
void git_threads_shutdown(void) void git_threads_shutdown(void)
{ {
/* Shut down any subsystems that have global state */ /* Shut down any subsystems that have global state */
git_hash_global_shutdown(); git__shutdown();
git_futils_dirs_free();
} }
git_global_st *git__global_state(void) git_global_st *git__global_state(void)
......
...@@ -21,4 +21,8 @@ extern git_mutex git__mwindow_mutex; ...@@ -21,4 +21,8 @@ extern git_mutex git__mwindow_mutex;
#define GIT_GLOBAL (git__global_state()) #define GIT_GLOBAL (git__global_state())
typedef void (*git_global_shutdown_fn)(void);
extern void git__on_shutdown(git_global_shutdown_fn callback);
#endif #endif
...@@ -13,8 +13,6 @@ typedef struct git_hash_prov git_hash_prov; ...@@ -13,8 +13,6 @@ typedef struct git_hash_prov git_hash_prov;
typedef struct git_hash_ctx git_hash_ctx; typedef struct git_hash_ctx git_hash_ctx;
int git_hash_global_init(void); int git_hash_global_init(void);
void git_hash_global_shutdown(void);
int git_hash_ctx_init(git_hash_ctx *ctx); int git_hash_ctx_init(git_hash_ctx *ctx);
void git_hash_ctx_cleanup(git_hash_ctx *ctx); void git_hash_ctx_cleanup(git_hash_ctx *ctx);
......
...@@ -17,7 +17,6 @@ struct git_hash_ctx { ...@@ -17,7 +17,6 @@ struct git_hash_ctx {
}; };
#define git_hash_global_init() 0 #define git_hash_global_init() 0
#define git_hash_global_shutdown() /* noop */
#define git_hash_ctx_init(ctx) git_hash_init(ctx) #define git_hash_ctx_init(ctx) git_hash_init(ctx)
#define git_hash_ctx_cleanup(ctx) #define git_hash_ctx_cleanup(ctx)
......
...@@ -17,7 +17,6 @@ struct git_hash_ctx { ...@@ -17,7 +17,6 @@ struct git_hash_ctx {
}; };
#define git_hash_global_init() 0 #define git_hash_global_init() 0
#define git_hash_global_shutdown() /* noop */
#define git_hash_ctx_init(ctx) git_hash_init(ctx) #define git_hash_ctx_init(ctx) git_hash_init(ctx)
#define git_hash_ctx_cleanup(ctx) #define git_hash_ctx_cleanup(ctx)
......
...@@ -89,7 +89,15 @@ GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void) ...@@ -89,7 +89,15 @@ GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void)
hash_prov.type = INVALID; hash_prov.type = INVALID;
} }
int git_hash_global_init() static void git_hash_global_shutdown(void)
{
if (hash_prov.type == CNG)
hash_cng_prov_shutdown();
else if(hash_prov.type == CRYPTOAPI)
hash_cryptoapi_prov_shutdown();
}
int git_hash_global_init(void)
{ {
int error = 0; int error = 0;
...@@ -99,15 +107,9 @@ int git_hash_global_init() ...@@ -99,15 +107,9 @@ int git_hash_global_init()
if ((error = hash_cng_prov_init()) < 0) if ((error = hash_cng_prov_init()) < 0)
error = hash_cryptoapi_prov_init(); error = hash_cryptoapi_prov_init();
return error; git__on_shutdown(git_hash_global_shutdown);
}
void git_hash_global_shutdown() return error;
{
if (hash_prov.type == CNG)
hash_cng_prov_shutdown();
else if(hash_prov.type == CRYPTOAPI)
hash_cryptoapi_prov_shutdown();
} }
/* CryptoAPI: available in Windows XP and newer */ /* CryptoAPI: available in Windows XP and newer */
......
...@@ -217,6 +217,14 @@ int pthread_rwlock_destroy(pthread_rwlock_t *lock) ...@@ -217,6 +217,14 @@ int pthread_rwlock_destroy(pthread_rwlock_t *lock)
} }
static void win32_pthread_shutdown(void)
{
if (win32_kernel32_dll) {
FreeLibrary(win32_kernel32_dll);
win32_kernel32_dll = NULL;
}
}
int win32_pthread_initialize(void) int win32_pthread_initialize(void)
{ {
if (win32_kernel32_dll) if (win32_kernel32_dll)
...@@ -239,15 +247,7 @@ int win32_pthread_initialize(void) ...@@ -239,15 +247,7 @@ int win32_pthread_initialize(void)
win32_srwlock_release_exclusive = (win32_srwlock_fn) win32_srwlock_release_exclusive = (win32_srwlock_fn)
GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive"); GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive");
return 0; git__on_shutdown(win32_pthread_shutdown);
}
int win32_pthread_shutdown(void)
{
if (win32_kernel32_dll) {
FreeLibrary(win32_kernel32_dll);
win32_kernel32_dll = NULL;
}
return 0; return 0;
} }
...@@ -69,6 +69,5 @@ int pthread_rwlock_wrunlock(pthread_rwlock_t *); ...@@ -69,6 +69,5 @@ int pthread_rwlock_wrunlock(pthread_rwlock_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *); int pthread_rwlock_destroy(pthread_rwlock_t *);
extern int win32_pthread_initialize(void); extern int win32_pthread_initialize(void);
extern int win32_pthread_shutdown(void);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment