summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/atexit.h19
-rw-r--r--src/atexit.c47
-rw-r--r--src/atexit.h44
-rw-r--r--src/global.c4
4 files changed, 113 insertions, 1 deletions
diff --git a/include/git2/atexit.h b/include/git2/atexit.h
new file mode 100644
index 000000000..cab8e1872
--- /dev/null
+++ b/include/git2/atexit.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_git_atexit_h__
+#define INCLUDE_git_atexit_h__
+
+#include "common.h"
+
+/**
+ * Execute cleanup for in-process operations
+ *
+ * This will e.g. delete lockfiles we own.
+ */
+GIT_EXTERN(int) git_atexit(void);
+
+#endif /* INCLUDE_git_atexit_h__ */
diff --git a/src/atexit.c b/src/atexit.c
new file mode 100644
index 000000000..1e15a15bc
--- /dev/null
+++ b/src/atexit.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "common.h"
+#include "vector.h"
+#include "atexit.h"
+
+static git_vector rollbacks;
+
+int git_atexit_global_init(void)
+{
+ return git_vector_init(&rollbacks, 0, NULL);
+}
+
+int git__atexit_register(git__atexit *atexit)
+{
+ return git_vector_insert(&rollbacks, atexit);
+}
+
+int git__atexit_unregister(git__atexit *atexit)
+{
+ int error;
+ size_t pos;
+
+ if ((error = git_vector_search(&pos, &rollbacks, atexit)) < 0)
+ return error;
+
+ return git_vector_remove(&rollbacks, pos);
+}
+
+int git_atexit(void)
+{
+ size_t i;
+ int error;
+ git__atexit *atexit;
+
+ git_vector_foreach(&rollbacks, i, atexit) {
+ if ((error = atexit->execute(atexit)) < 0)
+ return error;
+ }
+
+ return 0;
+}
diff --git a/src/atexit.h b/src/atexit.h
new file mode 100644
index 000000000..9ac9dd74c
--- /dev/null
+++ b/src/atexit.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+#ifndef INCLUDE_atexit_h__
+#define INCLUDE_atexit_h__
+
+#include "common.h"
+#include "git2/atexit.h"
+
+typedef struct git__atexit git__atexit;
+
+/**
+ * The signature of the function which will be called in order to execute this
+ * rollback.
+ */
+typedef int (*git__atexit_execute)(git__atexit *atexit);
+
+/**
+ * Include this header as the first element in your atexit cancellation
+ * structure.
+ */
+struct git__atexit {
+ /**
+ * Execute this rollback. This function may be called from any thread.
+ */
+ git__atexit_execute execute;
+};
+
+/**
+ * Register a rollback.
+ */
+int git__atexit_register(git__atexit* atexit);
+
+/**
+ * UnRegister a rollback.
+ */
+int git__atexit_unregister(git__atexit* atexit);
+
+int git_atexit_global_init(void);
+
+#endif
diff --git a/src/global.c b/src/global.c
index 89183080b..853f90270 100644
--- a/src/global.c
+++ b/src/global.c
@@ -15,6 +15,7 @@
#include "thread-utils.h"
#include "git2/global.h"
#include "transports/ssh.h"
+#include "atexit.h"
#if defined(GIT_MSVC_CRTDBG)
#include "win32/w32_stack.h"
@@ -63,7 +64,8 @@ static int init_common(void)
(ret = git_filter_global_init()) == 0 &&
(ret = git_merge_driver_global_init()) == 0 &&
(ret = git_transport_ssh_global_init()) == 0 &&
- (ret = git_openssl_stream_global_init()) == 0)
+ (ret = git_openssl_stream_global_init()) == 0 &&
+ (ret = git_atexit_global_init() == 0))
ret = git_mwindow_global_init();
GIT_MEMORY_BARRIER;