librelist archives

« back to archive

Usage of declspec(thread) in include/git2/thread-utils.h

Usage of declspec(thread) in include/git2/thread-utils.h

From:
Senthil Kumar
Date:
2011-06-09 @ 11:02
Hi,

I'm trying to use libgit2 on Windows as a static library linked into a
C++/CLI DLL. I was able to build the DLL and load it in a managed (C#)
application, but when trying to get a commit using git_commit_lookup, I'm
getting an access violation error. This is not happening in all machines -
on my Win7 x64 laptop, the code worked perfectly fine, but it consistently
fails on my Win XP SP3 32 bit machine.

I decided to debug and found that the access violation is occurring when
g_last_error is accessed in the git__throw function (src\errors.c).
Inspecting the g_last_error variable showed that it was pointing at a
garbage address. When I went to the definition, I found that it was
decorated with GIT_TLS, which in my Windows machine expands to
declspec(thread). Removing the decoration and recompiling/relinking fixed
the problem, but of course, the thread local nature of the last error
variable is gone.

As discussed in http://www.nynaeve.net/?p=180,
http://blogs.msdn.com/b/oldnewthing/archive/2010/11/22/10094489.aspx and
http://msdn.microsoft.com/en-us/library/ms682594.aspx, declspec(thread)
apparently only works for DLLs that are linked directly to executables ("
Specifically, implicit TLS does not operate when a module using it is not
being loaded at process initialization time (during static import
resolution)").  The CLR loads my C++/CLI DLL only when it needs to, and even
then, it uses LoadLibrary, which means that there is no hope of
declspec(thread) working correctly in this case.

Windows Vista (and later) operating systems apparently handle
declspec(thread) differently, so that's why it worked fine on my Win7
machine.

To summarize, the current implementation cannot be used a static library
linked to a C++/CLI (mixed mode) DLL, at least on pre-Windows Vista
machines. The alternative is to use the explicit TlsGetValue/TlsSetValue
functions.

Thoughts?

Regards
Senthil

Re: [libgit2] Usage of declspec(thread) in include/git2/thread-utils.h

From:
Vicent Marti
Date:
2011-06-09 @ 11:27
Hey Senthil,

this is a known issue that has been around our tracker for a while.
It's nice to see that you arrived to the same conclusion as Emeric and
I did when debugging it.

Currently, what we are doing on libgit2sharp (the .NET bindings for
libgit2) is building the library without threading support
(GIT_THREADS), which will completely disable all TLS declarations.

I'm working on a fix using the TlsValue methods from the Windows API
-- hopefully running libgit2 without threading will work as a
workaround for you until then.

Cheers!
Vicent

On Thu, Jun 9, 2011 at 1:02 PM, Senthil Kumar
<senthil.thecoder@gmail.com> wrote:
> Hi,
>
> I'm trying to use libgit2 on Windows as a static library linked into a
> C++/CLI DLL. I was able to build the DLL and load it in a managed (C#)
> application, but when trying to get a commit using git_commit_lookup, I'm
> getting an access violation error. This is not happening in all machines -
> on my Win7 x64 laptop, the code worked perfectly fine, but it consistently
> fails on my Win XP SP3 32 bit machine.
>
> I decided to debug and found that the access violation is occurring when
> g_last_error is accessed in the git__throw function (src\errors.c).
> Inspecting the g_last_error variable showed that it was pointing at a
> garbage address. When I went to the definition, I found that it was
> decorated with GIT_TLS, which in my Windows machine expands to
> declspec(thread). Removing the decoration and recompiling/relinking fixed
> the problem, but of course, the thread local nature of the last error
> variable is gone.
>
> As discussed in http://www.nynaeve.net/?p=180,
> http://blogs.msdn.com/b/oldnewthing/archive/2010/11/22/10094489.aspx and
> http://msdn.microsoft.com/en-us/library/ms682594.aspx, declspec(thread)
> apparently only works for DLLs that are linked directly to executables ("
> Specifically, implicit TLS does not operate when a module using it is not
> being loaded at process initialization time (during static import
> resolution)").  The CLR loads my C++/CLI DLL only when it needs to, and even
> then, it uses LoadLibrary, which means that there is no hope of
> declspec(thread) working correctly in this case.
>
> Windows Vista (and later) operating systems apparently handle
> declspec(thread) differently, so that's why it worked fine on my Win7
> machine.
>
> To summarize, the current implementation cannot be used a static library
> linked to a C++/CLI (mixed mode) DLL, at least on pre-Windows Vista
> machines. The alternative is to use the explicit TlsGetValue/TlsSetValue
> functions.
>
> Thoughts?
>
> Regards
> Senthil