summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2018-01-21 20:55:46 +0000
committerCarlos Martín Nieto <cmn@dwim.me>2018-01-21 21:09:52 +0000
commit8b66a8c6ec6dedd2a80d1c9d35eafebf49f5cead (patch)
treea9504277bdde528c3157fd614a814a9d3916de68
parent820370fe846167faaeabb2238cae900489af6bb8 (diff)
downloadlibgit2-cmn/atexit-skeleton.tar.gz
atexit: create skeletoncmn/atexit-skeleton
This provides a skeleton for registering rollback functions in case the caller wants to centralise their error handling in an `atexit(3)`-like manner. Subsystems within libgit2 will register themselves when they e.g. create lockfiles. If the caller detects an error (potentially unrelated to the libgit2 operation) and wants to back out, they could call `git_atexit()` in order to remove lockfiles which the library is holding.
-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;