@@ -17,62 +17,13 @@ internal static partial class NativeMethods
1717 {
1818 public const uint GIT_PATH_MAX = 4096 ;
1919 private const string libgit2 = NativeDllName . Name ;
20- // This is here to keep the pointer alive
21- #pragma warning disable 0414
22- private static readonly LibraryLifetimeObject lifetimeObject ;
23- #pragma warning restore 0414
24- private static int handlesCount ;
25-
26- /// <summary>
27- /// Internal hack to ensure that the call to git_threads_shutdown is called after all handle finalizers
28- /// have run to completion ensuring that no dangling git-related finalizer runs after git_threads_shutdown.
29- /// There should never be more than one instance of this object per AppDomain.
30- /// </summary>
31- private sealed class LibraryLifetimeObject
32- #if DESKTOP
33- : CriticalFinalizerObject
34- #endif
35- {
36- // Ensure mono can JIT the .cctor and adjust the PATH before trying to load the native library.
37- // See https://github.com/libgit2/libgit2sharp/pull/190
38- [ MethodImpl ( MethodImplOptions . NoInlining ) ]
39- public LibraryLifetimeObject ( )
40- {
41- int res = git_libgit2_init ( ) ;
42- Ensure . Int32Result ( res ) ;
43- if ( res == 1 )
44- {
45- // Ignore the error that this propagates. Call it in case openssl is being used.
46- git_openssl_set_locking ( ) ;
47- }
48- AddHandle ( ) ;
49- }
50-
51- ~ LibraryLifetimeObject ( )
52- {
53- RemoveHandle ( ) ;
54- }
55- }
56-
57- #if DESKTOP
58- [ ReliabilityContract ( Consistency . WillNotCorruptState , Cer . Success ) ]
59- #endif
60- internal static void AddHandle ( )
61- {
62- Interlocked . Increment ( ref handlesCount ) ;
63- }
6420
65- #if DESKTOP
66- [ ReliabilityContract ( Consistency . WillNotCorruptState , Cer . Success ) ]
67- #endif
68- internal static void RemoveHandle ( )
69- {
70- int count = Interlocked . Decrement ( ref handlesCount ) ;
71- if ( count == 0 )
72- {
73- git_libgit2_shutdown ( ) ;
74- }
75- }
21+ // An object tied to the lifecycle of the NativeMethods static class.
22+ // This will handle initialization and shutdown of the underlying
23+ // native library.
24+ #pragma warning disable 0414
25+ private static readonly NativeShutdownObject shutdownObject ;
26+ #pragma warning restore 0414
7627
7728 static NativeMethods ( )
7829 {
@@ -87,8 +38,30 @@ static NativeMethods()
8738 String . Format ( CultureInfo . InvariantCulture , "{0}{1}{2}" , path , Path . PathSeparator , Environment . GetEnvironmentVariable ( pathEnvVariable ) ) ) ;
8839 }
8940
90- // See LibraryLifetimeObject description.
91- lifetimeObject = new LibraryLifetimeObject ( ) ;
41+ LoadNativeLibrary ( ) ;
42+ shutdownObject = new NativeShutdownObject ( ) ;
43+ }
44+
45+ // Avoid inlining this method because otherwise mono's JITter may try
46+ // to load the library _before_ we've configured the path.
47+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
48+ private static void LoadNativeLibrary ( )
49+ {
50+ // Configure the OpenSSL locking on the true initialization
51+ // of the library.
52+ if ( git_libgit2_init ( ) == 1 )
53+ {
54+ git_openssl_set_locking ( ) ;
55+ }
56+ }
57+
58+ // Shutdown the native library in a finalizer.
59+ private sealed class NativeShutdownObject
60+ {
61+ ~ NativeShutdownObject ( )
62+ {
63+ git_libgit2_shutdown ( ) ;
64+ }
9265 }
9366
9467 [ DllImport ( libgit2 ) ]
0 commit comments