mirror of
				https://git.proxmox.com/git/libgit2
				synced 2025-11-04 08:48:25 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									e7d0ced219
								
							
						
					
					
						commit
						a3aa5f4d5d
					
				@ -6,6 +6,7 @@
 | 
			
		||||
 */
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "fileops.h"
 | 
			
		||||
#include "global.h"
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#if GIT_WIN32
 | 
			
		||||
#include "win32/findfile.h"
 | 
			
		||||
@ -635,6 +636,13 @@ static git_futils_dirs_guess_cb git_futils__dir_guess[GIT_FUTILS_DIR__MAX] = {
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	git_futils_dir_t i;
 | 
			
		||||
@ -644,6 +652,8 @@ int git_futils_dirs_global_init(void)
 | 
			
		||||
	for (i = 0; !error && i < GIT_FUTILS_DIR__MAX; i++)
 | 
			
		||||
		error = git_futils_dirs_get(&path, i);
 | 
			
		||||
 | 
			
		||||
	git__on_shutdown(git_futils_dirs_global_shutdown);
 | 
			
		||||
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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(
 | 
			
		||||
	git_buf *path, const char *name, git_futils_dir_t which, const char *label)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -353,11 +353,6 @@ extern int git_futils_dirs_get_str(
 | 
			
		||||
 */
 | 
			
		||||
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).
 | 
			
		||||
 *
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								src/global.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/global.c
									
									
									
									
									
								
							@ -14,6 +14,28 @@
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 *
 | 
			
		||||
@ -79,9 +101,7 @@ int git_threads_init(void)
 | 
			
		||||
void git_threads_shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Shut down any subsystems that have global state */
 | 
			
		||||
	win32_pthread_shutdown();
 | 
			
		||||
	git_futils_dirs_free();
 | 
			
		||||
	git_hash_global_shutdown();
 | 
			
		||||
	git__shutdown();
 | 
			
		||||
 | 
			
		||||
	TlsFree(_tls_index);
 | 
			
		||||
	_tls_init = 0;
 | 
			
		||||
@ -140,6 +160,9 @@ int git_threads_init(void)
 | 
			
		||||
 | 
			
		||||
void git_threads_shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Shut down any subsystems that have global state */
 | 
			
		||||
	git__shutdown();
 | 
			
		||||
 | 
			
		||||
	if (_tls_init) {
 | 
			
		||||
		void *ptr = pthread_getspecific(_tls_key);
 | 
			
		||||
		pthread_setspecific(_tls_key, NULL);
 | 
			
		||||
@ -149,10 +172,6 @@ void git_threads_shutdown(void)
 | 
			
		||||
	pthread_key_delete(_tls_key);
 | 
			
		||||
	_tls_init = 0;
 | 
			
		||||
	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)
 | 
			
		||||
@ -179,15 +198,14 @@ static git_global_st __state;
 | 
			
		||||
 | 
			
		||||
int git_threads_init(void)
 | 
			
		||||
{
 | 
			
		||||
	/* noop */ 
 | 
			
		||||
	/* noop */
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void git_threads_shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	/* Shut down any subsystems that have global state */
 | 
			
		||||
	git_hash_global_shutdown();
 | 
			
		||||
	git_futils_dirs_free();
 | 
			
		||||
	git__shutdown();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
git_global_st *git__global_state(void)
 | 
			
		||||
 | 
			
		||||
@ -21,4 +21,8 @@ extern git_mutex git__mwindow_mutex;
 | 
			
		||||
 | 
			
		||||
#define GIT_GLOBAL (git__global_state())
 | 
			
		||||
 | 
			
		||||
typedef void (*git_global_shutdown_fn)(void);
 | 
			
		||||
 | 
			
		||||
extern void git__on_shutdown(git_global_shutdown_fn callback);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,6 @@ typedef struct git_hash_prov git_hash_prov;
 | 
			
		||||
typedef struct git_hash_ctx git_hash_ctx;
 | 
			
		||||
 | 
			
		||||
int git_hash_global_init(void);
 | 
			
		||||
void git_hash_global_shutdown(void);
 | 
			
		||||
 | 
			
		||||
int git_hash_ctx_init(git_hash_ctx *ctx);
 | 
			
		||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,6 @@ struct git_hash_ctx {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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_cleanup(ctx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,6 @@ struct git_hash_ctx {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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_cleanup(ctx)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,15 @@ GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void)
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
@ -99,15 +107,9 @@ int git_hash_global_init()
 | 
			
		||||
	if ((error = hash_cng_prov_init()) < 0)
 | 
			
		||||
		error = hash_cryptoapi_prov_init();
 | 
			
		||||
 | 
			
		||||
	return error;	
 | 
			
		||||
}
 | 
			
		||||
	git__on_shutdown(git_hash_global_shutdown);
 | 
			
		||||
 | 
			
		||||
void git_hash_global_shutdown()
 | 
			
		||||
{
 | 
			
		||||
	if (hash_prov.type == CNG)
 | 
			
		||||
		hash_cng_prov_shutdown();
 | 
			
		||||
	else if(hash_prov.type == CRYPTOAPI)
 | 
			
		||||
		hash_cryptoapi_prov_shutdown();
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* CryptoAPI: available in Windows XP and newer */
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
{
 | 
			
		||||
	if (win32_kernel32_dll)
 | 
			
		||||
@ -239,15 +247,7 @@ int win32_pthread_initialize(void)
 | 
			
		||||
	win32_srwlock_release_exclusive = (win32_srwlock_fn)
 | 
			
		||||
		GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive");
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int win32_pthread_shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	if (win32_kernel32_dll) {
 | 
			
		||||
		FreeLibrary(win32_kernel32_dll);
 | 
			
		||||
		win32_kernel32_dll = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	git__on_shutdown(win32_pthread_shutdown);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -69,6 +69,5 @@ int pthread_rwlock_wrunlock(pthread_rwlock_t *);
 | 
			
		||||
int pthread_rwlock_destroy(pthread_rwlock_t *);
 | 
			
		||||
 | 
			
		||||
extern int win32_pthread_initialize(void);
 | 
			
		||||
extern int win32_pthread_shutdown(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user