Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
7bb63991
Commit
7bb63991
authored
Nov 06, 2014
by
Edward Thomson
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2676 from libgit2/cmn/threading
Threading and crypto libraries
parents
f890a84f
15bea02c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
124 additions
and
18 deletions
+124
-18
README.md
+5
-0
THREADING.md
+79
-0
include/git2/threads.h
+16
-0
src/global.c
+24
-18
No files found.
README.md
View file @
7bb63991
...
...
@@ -58,6 +58,11 @@ dependencies, it can make use of a few libraries to add to it:
-
LibSSH2 to enable the SSH transport
-
iconv (OSX) to handle the HFS+ path encoding peculiarities
Threading
=========
See
[
THREADING
](
THREADING.md
)
for information
Building libgit2 - Using CMake
==============================
...
...
THREADING.md
0 → 100644
View file @
7bb63991
Threads in libgit2
==================
You may safely use any libgit2 object from any thread, though there
may be issues depending on the cryptographic libraries libgit2 or its
dependencies link to (more on this later). For libgit2 itself,
provided you take the following into consideration you won't run into
issues:
Sharing objects
---------------
Use an object from a single thread at a time. Most data structures do
not guard against concurrent access themselves. This is because they
are rarely used in isolation and it makes more sense to synchronize
access via a larger lock or similar mechanism.
There are some objects which are read-only/immutable and are thus safe
to share across threads, such as references and configuration
snapshots.
Error messages
--------------
The error message is thread-local. The
`giterr_last()`
call must
happen on the same thread as the error in order to get the
message. Often this will be the case regardless, but if you use
something like the GDC on MacOS (where code is executed on an
arbitrary thread), the code must make sure to retrieve the error code
on the thread where the error happened.
Threads and cryptographic libraries
=======================================
On Windows
----------
When built as a native Windows DLL, libgit2 uses WinCNG and WinHTTP,
both of which are thread-safe. You do not need to do anything special.
When using libssh2 which itself uses WinCNG, there are no special
steps necessary. If you are using a MinGW or similar environment where
libssh2 uses OpenSSL or libgcrypt, then the non-Windows case affects
you.
Non-Windows
-----------
On the rest of the platforms, libgit2 uses OpenSSL to be able to use
HTTPS as a transport. This library is made to be thread-implementation
agnostic, and the users of the library must set which locking function
it should use. This means that libgit2 cannot know what to set as the
user of libgit2 may use OpenSSL independently and the locking settings
must survive libgit2 shutting down.
libgit2 does provide a convenience function
`git_openssl_set_locking()`
to use the platform-native mutex
mechanisms to perform the locking, which you may rely on if you do not
want to use OpenSSL outside of libgit2, or you know that libgit2 will
outlive the rest of the operations. It is not safe to use OpenSSL
multi-threaded after libgit2's shutdown function has been called.
See the
[
OpenSSL documentation
](
https://www.openssl.org/docs/crypto/threads.html
)
on threading for more details.
libssh2 may be linked against OpenSSL or libgcrypt. If it uses
OpenSSL, you only need to set up threading for OpenSSL once and the
above paragraphs are enough. If it uses libgcrypt, then you need to
set up its locking before using it multi-threaded. libgit2 has no
direct connection to libgcrypt and thus has not convenience functions for
it (but libgcrypt has macros). Read libgcrypt's
[
threading documentation for more information
](
http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
)
It is your responsibility as an application author or packager to know
what your dependencies are linked against and to take the appropriate
steps to ensure the cryptographic libraries are thread-safe. We agree
that this situation is far from ideal but at this time it is something
the application authors need to deal with.
include/git2/threads.h
View file @
7bb63991
...
...
@@ -44,6 +44,22 @@ GIT_EXTERN(int) git_threads_init(void);
*/
GIT_EXTERN
(
void
)
git_threads_shutdown
(
void
);
/**
* Initialize the OpenSSL locks
*
* OpenSSL requires the application to determine how it performs
* locking. This is a convenience function which libgit2 provides for
* allocating and initializing the locks as well as setting the
* locking function to use the system's native locking functions.
*
* The locking function will be cleared and the memory will be freed
* when you call git_threads_sutdown().
*
* @return 0 on success, -1 if there are errors or if libgit2 was not
* built with OpenSSL and threading support.
*/
GIT_EXTERN
(
int
)
git_openssl_set_locking
(
void
);
/** @} */
GIT_END_DECL
#endif
...
...
src/global.c
View file @
7bb63991
...
...
@@ -64,8 +64,9 @@ void openssl_locking_function(int mode, int n, const char *file, int line)
}
}
static
void
shutdown_ssl
(
void
)
static
void
shutdown_ssl
_locking
(
void
)
{
CRYPTO_set_locking_callback
(
NULL
);
git__free
(
openssl_locks
);
}
#endif
...
...
@@ -96,30 +97,35 @@ static void init_ssl(void)
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
}
#endif
}
int
git_openssl_set_locking
(
void
)
{
#ifdef GIT_SSL
# ifdef GIT_THREADS
{
int
num_locks
,
i
;
num_locks
=
CRYPTO_num_locks
();
openssl_locks
=
git__calloc
(
num_locks
,
sizeof
(
git_mutex
));
if
(
openssl_locks
==
NULL
)
{
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
}
int
num_locks
,
i
;
for
(
i
=
0
;
i
<
num_locks
;
i
++
)
{
if
(
git_mutex_init
(
&
openssl_locks
[
i
])
!=
0
)
{
SSL_CTX_free
(
git__ssl_ctx
);
git__ssl_ctx
=
NULL
;
}
}
num_locks
=
CRYPTO_num_locks
();
openssl_locks
=
git__calloc
(
num_locks
,
sizeof
(
git_mutex
));
GITERR_CHECK_ALLOC
(
openssl_locks
);
CRYPTO_set_locking_callback
(
openssl_locking_function
);
for
(
i
=
0
;
i
<
num_locks
;
i
++
)
{
if
(
git_mutex_init
(
&
openssl_locks
[
i
])
!=
0
)
{
giterr_set
(
GITERR_SSL
,
"failed to initialize openssl locks"
);
return
-
1
;
}
}
git__on_shutdown
(
shutdown_ssl
);
CRYPTO_set_locking_callback
(
openssl_locking_function
);
git__on_shutdown
(
shutdown_ssl_locking
);
return
0
;
# else
giterr_set
(
GITERR_THREAD
,
"libgit2 as not built with threads"
);
return
-
1
;
# endif
giterr_set
(
GITERR_SSL
,
"libgit2 was not built with OpenSSL support"
);
return
-
1
;
#endif
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment