On Windows platforms, we automatically clean up the thread-local storage
upon detaching a thread via `DllMain()`. The thing is that this happens
for every thread of applications that link against the libgit2 DLL, even
those that don't have anything to do with libgit2 itself. As a result,
we cannot assume that these unsuspecting threads make use of our
`git_libgit2_init()` and `git_libgit2_shutdow()` reference counting,
which may lead to racy situations:
Thread 1 Thread 2
git_libgit2_shutdown()
DllMain(DETACH_THREAD)
git__free_tls_data()
git_atomic_dec() == 0
git__free_tls_data()
TlsFree(_tls_index)
TlsGetValue(_tls_index)
Due to the second thread never having executed `git_libgit2_init()`, the
first thread will clean up TLS data and as a result also free the
`_tls_index` variable. When detaching the second thread, we
unconditionally access the now-free'd `_tls_index` variable, which is
obviously not going to work out well.
Fix the issue by converting the code to use fiber-local storage instead
of thread-local storage. While FLS will behave the exact same as TLS if
no fibers are in use, it does allow us to specify a destructor similar
to the one that is accepted by pthread_key_create(3P). Like this, we do
not have to manually free indices anymore, but will let the FLS handle
calling the destructor. This allows us to get rid of `DllMain()`
completely, as we only used it to keep track of when threads were
exiting and results in an overall simplification of TLS cleanup.
| Name |
Last commit
|
Last update |
|---|---|---|
| .. | ||
| dir.c | Loading commit data... | |
| dir.h | Loading commit data... | |
| error.c | Loading commit data... | |
| error.h | Loading commit data... | |
| findfile.c | Loading commit data... | |
| findfile.h | Loading commit data... | |
| git2.rc | Loading commit data... | |
| map.c | Loading commit data... | |
| mingw-compat.h | Loading commit data... | |
| msvc-compat.h | Loading commit data... | |
| path_w32.c | Loading commit data... | |
| path_w32.h | Loading commit data... | |
| posix.h | Loading commit data... | |
| posix_w32.c | Loading commit data... | |
| precompiled.c | Loading commit data... | |
| precompiled.h | Loading commit data... | |
| reparse.h | Loading commit data... | |
| thread.c | Loading commit data... | |
| thread.h | Loading commit data... | |
| utf-conv.c | Loading commit data... | |
| utf-conv.h | Loading commit data... | |
| version.h | Loading commit data... | |
| w32_buffer.c | Loading commit data... | |
| w32_buffer.h | Loading commit data... | |
| w32_common.h | Loading commit data... | |
| w32_crtdbg_stacktrace.c | Loading commit data... | |
| w32_crtdbg_stacktrace.h | Loading commit data... | |
| w32_stack.c | Loading commit data... | |
| w32_stack.h | Loading commit data... | |
| w32_util.c | Loading commit data... | |
| w32_util.h | Loading commit data... | |
| win32-compat.h | Loading commit data... |