Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d45523c

Browse files
committed
Bring back LeaksContainer
It went away when removing the base safe handle, but we need it for the debug/CI builds.
1 parent c9c49b1 commit d45523c

File tree

3 files changed

+116
-5
lines changed

3 files changed

+116
-5
lines changed

LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ public virtual void Dispose()
234234
if (LeaksContainer.TypeNames.Any())
235235
{
236236
Assert.False(true, string.Format("Some handles of the following types haven't been properly released: {0}.{1}"
237-
+ "In order to get some help fixing those leaks, uncomment the define LEAKS_TRACKING in SafeHandleBase.cs{1}"
237+
+ "In order to get some help fixing those leaks, uncomment the define LEAKS_TRACKING in Libgit2Object.cs{1}"
238238
+ "and run the tests locally.", string.Join(", ", LeaksContainer.TypeNames), Environment.NewLine));
239239
}
240240
#endif

LibGit2Sharp/Core/Handles/Libgit2Object.cs

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,90 @@
1-
using System;
1+
// This activates a lightweight mode which will help put under the light
2+
// incorrectly released handles by outputing a warning message in the console.
3+
//
4+
// This should be activated when tests are being run of the CI server.
5+
//
6+
// Uncomment the line below or add a conditional symbol to activate this mode
7+
8+
// #define LEAKS_IDENTIFYING
9+
10+
// This activates a more throrough mode which will show the stack trace of the
11+
// allocation code path for each handle that has been improperly released.
12+
//
13+
// This should be manually activated when some warnings have been raised as
14+
// a result of LEAKS_IDENTIFYING mode activation.
15+
//
16+
// Uncomment the line below or add a conditional symbol to activate this mode
17+
18+
// #define LEAKS_TRACKING
19+
20+
using System;
21+
using System.Linq;
22+
using System.Diagnostics;
23+
using System.Globalization;
24+
using System.Collections.Generic;
25+
26+
#if LEAKS_IDENTIFYING
27+
namespace LibGit2Sharp.Core
28+
{
29+
/// <summary>
30+
/// Holds leaked handle type names reported by <see cref="Core.Handles.Libgit2Object"/>
31+
/// </summary>
32+
public static class LeaksContainer
33+
{
34+
private static readonly HashSet<string> _typeNames = new HashSet<string>();
35+
private static readonly object _lockpad = new object();
36+
37+
/// <summary>
38+
/// Report a new leaked handle type name
39+
/// </summary>
40+
/// <param name="typeName">Short name of the leaked handle type.</param>
41+
public static void Add(string typeName)
42+
{
43+
lock (_lockpad)
44+
{
45+
_typeNames.Add(typeName);
46+
}
47+
}
48+
49+
/// <summary>
50+
/// Removes all previously reported leaks.
51+
/// </summary>
52+
public static void Clear()
53+
{
54+
lock (_lockpad)
55+
{
56+
_typeNames.Clear();
57+
}
58+
}
59+
60+
/// <summary>
61+
/// Returns all reported leaked handle type names.
62+
/// </summary>
63+
public static IEnumerable<string> TypeNames
64+
{
65+
get
66+
{
67+
string[] result = null;
68+
lock (_lockpad)
69+
{
70+
result = _typeNames.ToArray();
71+
}
72+
return result;
73+
}
74+
}
75+
}
76+
}
77+
#endif
278

379
namespace LibGit2Sharp.Core.Handles
480
{
581
internal unsafe abstract class Libgit2Object : IDisposable
682
{
83+
#if LEAKS_TRACKING
84+
private readonly string trace;
85+
private readonly Guid id;
86+
#endif
87+
788
protected void* ptr;
889

990
internal void* Handle
@@ -21,12 +102,17 @@ internal unsafe Libgit2Object(void* handle, bool owned)
21102
{
22103
this.ptr = handle;
23104
this.owned = owned;
105+
106+
#if LEAKS_TRACKING
107+
id = Guid.NewGuid();
108+
Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Allocating {0} handle ({1})", GetType().Name, id));
109+
trace = new StackTrace(2, true).ToString();
110+
#endif
24111
}
25112

26113
internal unsafe Libgit2Object(IntPtr ptr, bool owned)
114+
: this(ptr.ToPointer(), owned)
27115
{
28-
this.ptr = ptr.ToPointer();
29-
this.owned = owned;
30116
}
31117

32118
~Libgit2Object()
@@ -51,6 +137,15 @@ internal IntPtr AsIntPtr()
51137

52138
void Dispose(bool disposing)
53139
{
140+
#if LEAKS_IDENTIFYING
141+
bool leaked = !disposing && ptr != null;
142+
143+
if (leaked)
144+
{
145+
LeaksContainer.Add(GetType().Name);
146+
}
147+
#endif
148+
54149
if (!disposed)
55150
{
56151
if (owned)
@@ -62,6 +157,19 @@ void Dispose(bool disposing)
62157
}
63158

64159
disposed = true;
160+
161+
#if LEAKS_TRACKING
162+
if (!leaked)
163+
{
164+
Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Disposing {0} handle ({1})", GetType().Name, id));
165+
}
166+
else
167+
{
168+
Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Unexpected finalization of {0} handle ({1})", GetType().Name, id));
169+
Trace.WriteLine(trace);
170+
Trace.WriteLine("");
171+
}
172+
#endif
65173
}
66174

67175
public void Dispose()

LibGit2Sharp/Tree.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ internal string Path
7777

7878
unsafe TreeEntry byIndex(ObjectSafeWrapper obj, uint i, ObjectId parentTreeId, Repository repo, FilePath parentPath)
7979
{
80-
return new TreeEntry(Proxy.git_tree_entry_byindex(obj.ObjectPtr, i), parentTreeId, repo, parentPath);
80+
using (var entryHandle = Proxy.git_tree_entry_byindex(obj.ObjectPtr, i))
81+
{
82+
return new TreeEntry(entryHandle, parentTreeId, repo, parentPath);
83+
}
8184
}
8285

8386
/// <summary>

0 commit comments

Comments
 (0)