Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0d5a10c

Browse files
committedNov 21, 2024··
Use SafeHandles
1 parent 5efe9d8 commit 0d5a10c

File tree

6 files changed

+183
-172
lines changed

6 files changed

+183
-172
lines changed
 
+23-64
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
// This activates a lightweight mode which will help put under the light
2-
// incorrectly released handles by outputing a warning message in the console.
2+
// incorrectly released handles by outputting a warning message in the console.
33
//
44
// This should be activated when tests are being run on the CI server.
55
//
66
// Uncomment the line below or add a conditional symbol to activate this mode
77

8-
// #define LEAKS_IDENTIFYING
8+
//#define LEAKS_IDENTIFYING
99

10-
// This activates a more throrough mode which will show the stack trace of the
10+
// This activates a more thorough mode which will show the stack trace of the
1111
// allocation code path for each handle that has been improperly released.
1212
//
1313
// This should be manually activated when some warnings have been raised as
1414
// a result of LEAKS_IDENTIFYING mode activation.
1515
//
1616
// Uncomment the line below or add a conditional symbol to activate this mode
1717

18-
// #define LEAKS_TRACKING
18+
//#define LEAKS_TRACKING
1919

2020
using System;
21-
using System.Linq;
22-
using System.Diagnostics;
23-
using System.Globalization;
24-
using System.Collections.Generic;
21+
using Microsoft.Win32.SafeHandles;
2522

2623
#if LEAKS_IDENTIFYING
2724
namespace LibGit2Sharp.Core
2825
{
26+
using System.Collections.Generic;
27+
using System.Linq;
28+
2929
/// <summary>
3030
/// Holds leaked handle type names reported by <see cref="Core.Handles.Libgit2Object"/>
3131
/// </summary>
@@ -78,30 +78,27 @@ public static IEnumerable<string> TypeNames
7878

7979
namespace LibGit2Sharp.Core.Handles
8080
{
81-
internal unsafe abstract class Libgit2Object : IDisposable
81+
#if LEAKS_TRACKING
82+
using System.Diagnostics;
83+
using System.Globalization;
84+
#endif
85+
86+
internal unsafe abstract class Libgit2Object : SafeHandleZeroOrMinusOneIsInvalid
8287
{
8388
#if LEAKS_TRACKING
8489
private readonly string trace;
8590
private readonly Guid id;
8691
#endif
8792

88-
protected void* ptr;
89-
90-
internal void* Handle
93+
internal unsafe Libgit2Object(void* ptr, bool owned)
94+
: this(new IntPtr(ptr), owned)
9195
{
92-
get
93-
{
94-
return ptr;
95-
}
9696
}
9797

98-
bool owned;
99-
bool disposed;
100-
101-
internal unsafe Libgit2Object(void* handle, bool owned)
98+
internal unsafe Libgit2Object(IntPtr ptr, bool owned)
99+
: base(owned)
102100
{
103-
this.ptr = handle;
104-
this.owned = owned;
101+
SetHandle(ptr);
105102

106103
#if LEAKS_TRACKING
107104
id = Guid.NewGuid();
@@ -111,53 +108,20 @@ internal unsafe Libgit2Object(void* handle, bool owned)
111108
#endif
112109
}
113110

114-
internal unsafe Libgit2Object(IntPtr ptr, bool owned)
115-
: this(ptr.ToPointer(), owned)
116-
{
117-
}
111+
internal IntPtr AsIntPtr() => DangerousGetHandle();
118112

119-
~Libgit2Object()
120-
{
121-
Dispose(false);
122-
}
123-
124-
internal bool IsNull
125-
{
126-
get
127-
{
128-
return ptr == null;
129-
}
130-
}
131-
132-
internal IntPtr AsIntPtr()
133-
{
134-
return new IntPtr(ptr);
135-
}
136-
137-
public abstract void Free();
138-
139-
void Dispose(bool disposing)
113+
protected override void Dispose(bool disposing)
140114
{
141115
#if LEAKS_IDENTIFYING
142-
bool leaked = !disposing && ptr != null;
116+
bool leaked = !disposing && DangerousGetHandle() != IntPtr.Zero;
143117

144118
if (leaked)
145119
{
146120
LeaksContainer.Add(GetType().Name);
147121
}
148122
#endif
149123

150-
if (!disposed)
151-
{
152-
if (owned)
153-
{
154-
Free();
155-
}
156-
157-
ptr = null;
158-
}
159-
160-
disposed = true;
124+
base.Dispose(disposing);
161125

162126
#if LEAKS_TRACKING
163127
if (!leaked)
@@ -172,11 +136,6 @@ void Dispose(bool disposing)
172136
}
173137
#endif
174138
}
175-
176-
public void Dispose()
177-
{
178-
Dispose(true);
179-
}
180139
}
181140
}
182141

‎LibGit2Sharp/Core/Handles/Objects.cs

+150-100
Large diffs are not rendered by default.

‎LibGit2Sharp/Core/Handles/Objects.tt

+5-3
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,16 @@ for (var i = 0; i < cNames.Length; i++)
8282
{
8383
}
8484

85-
public override void Free()
85+
protected override bool ReleaseHandle()
8686
{
87-
NativeMethods.<#= cNames[i] #>_free((<#= cNames[i] #>*) ptr);
87+
NativeMethods.<#= cNames[i] #>_free((<#= cNames[i] #>*)DangerousGetHandle());
88+
89+
return true;
8890
}
8991

9092
public static implicit operator <#= cNames[i] #>*(<#= csNames[i] #> handle)
9193
{
92-
return (<#= cNames[i] #>*) handle.Handle;
94+
return (<#= cNames[i] #>*)handle.DangerousGetHandle();
9395
}
9496
}
9597

‎LibGit2Sharp/Network.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,11 @@ private IEnumerable<Reference> ListReferencesInternal(string url, CredentialsHan
216216

217217
static RemoteHandle BuildRemoteHandle(RepositoryHandle repoHandle, string url)
218218
{
219-
Debug.Assert(repoHandle != null && !repoHandle.IsNull);
219+
Debug.Assert(repoHandle != null && !repoHandle.IsInvalid);
220220
Debug.Assert(url != null);
221221

222222
RemoteHandle remoteHandle = Proxy.git_remote_create_anonymous(repoHandle, url);
223-
Debug.Assert(remoteHandle != null && !(remoteHandle.IsNull));
223+
Debug.Assert(remoteHandle != null && !remoteHandle.IsInvalid);
224224

225225
return remoteHandle;
226226
}

‎LibGit2Sharp/Reference.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ private protected Reference(IRepository repo, string canonicalName, string targe
3535
// This overload lets public-facing methods avoid having to use the pointers directly
3636
internal static unsafe T BuildFromPtr<T>(ReferenceHandle handle, Repository repo) where T : Reference
3737
{
38-
return BuildFromPtr<T>((git_reference*) handle.Handle, repo);
38+
return BuildFromPtr<T>((git_reference*)handle.AsIntPtr(), repo);
3939
}
4040

4141
internal static unsafe T BuildFromPtr<T>(git_reference* handle, Repository repo) where T : Reference

‎LibGit2Sharp/Repository.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ internal GitObject LookupInternal(ObjectId id, GitObjectType type, string knownP
575575

576576
using (ObjectHandle obj = Proxy.git_object_lookup(handle, id, type))
577577
{
578-
if (obj == null || obj.IsNull)
578+
if (obj == null || obj.IsInvalid)
579579
{
580580
return null;
581581
}
@@ -1781,7 +1781,7 @@ public void RevParse(string revision, out Reference reference, out GitObject obj
17811781
using (var objH = handles.Item1)
17821782
using (var refH = handles.Item2)
17831783
{
1784-
reference = refH.IsNull ? null : Reference.BuildFromPtr<Reference>(refH, this);
1784+
reference = refH.IsInvalid ? null : Reference.BuildFromPtr<Reference>(refH, this);
17851785
obj = GitObject.BuildFrom(this, Proxy.git_object_id(objH), Proxy.git_object_type(objH), PathFromRevparseSpec(revision));
17861786
}
17871787
}

0 commit comments

Comments
 (0)
Please sign in to comment.