Skip to content

Commit 91b2a2f

Browse files
authored
Simplify and fix the detection of XEL fields / actions (#117)
* Fixes a exception being raised when extracting fields / actions from multiple XEL files, and if the earlier file had reached sampling limit. * Removes cancellation support for this XEL fields / action detection method, thereby simplifying the implementation. As this method is typically very quick (as it is sampled) the lack of cancellation is acceptable.
1 parent 5762333 commit 91b2a2f

4 files changed

Lines changed: 12 additions & 26 deletions

File tree

Engine/StackResolver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ public class StackResolver : IDisposable {
2929
private static readonly Regex rgxAlreadySymbolizedFrame = new (@"((?<framenum>\d+)\s+)*(?<module>\w+)(\.(dll|exe))*!(?<symbolizedfunc>.+?)\s*\+\s*(0[xX])*(?<offset>[0-9a-fA-F]+)\s*", rgxOptions);
3030
private static readonly Regex rgxmoduleaddress = new (@"^\s*(?<filepath>.+)(\t+| +)(?<baseaddress>(0x)?[0-9a-fA-F`]+)\s*$", RegexOptions.Multiline);
3131

32-
public Task<Tuple<List<string>, List<string>>> GetDistinctXELFieldsAsync(string[] xelFiles, int eventsToSample, CancellationTokenSource cts) {
33-
return XELHelper.GetDistinctXELActionsFieldsAsync(xelFiles, eventsToSample, cts);
32+
public Task<Tuple<List<string>, List<string>>> GetDistinctXELFieldsAsync(string[] xelFiles, int eventsToSample) {
33+
return XELHelper.GetDistinctXELActionsFieldsAsync(xelFiles, eventsToSample);
3434
}
3535

3636
/// Public method which to help import XEL files

Engine/XELHelper.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,29 +78,27 @@ await xeStream.ReadEventStream(evt => {
7878
});
7979
}
8080

81-
internal async static Task<Tuple<List<string>, List<string>>> GetDistinctXELActionsFieldsAsync(string[] xelFiles, int eventsToSampleFromEachFile, CancellationTokenSource cts) {
81+
internal async static Task<Tuple<List<string>, List<string>>> GetDistinctXELActionsFieldsAsync(string[] xelFiles, int eventsToSampleFromEachFile) {
8282
return await Task.Run(async () => {
8383
Contract.Requires(xelFiles != null && eventsToSampleFromEachFile > 0);
8484
var allActions = new HashSet<string>();
8585
var allFields = new HashSet<string>();
86-
bool internalCancel = false;
8786
foreach (var file in xelFiles) {
8887
var numEvents = 0;
8988
var xeStream = new XEFileEventStreamer(file);
9089
try {
90+
// If preceeding file had issued an "internal cancel" (due to number of sampled events reached)
91+
// then create a new CTS to ensure subsequent files (if any) are also sampled correctly.
92+
using var cts = new CancellationTokenSource();
9193
await xeStream.ReadEventStream(evt => {
92-
if (Interlocked.Increment(ref numEvents) > eventsToSampleFromEachFile) {
93-
internalCancel = true;
94-
cts.Cancel();
95-
}
94+
if (Interlocked.Increment(ref numEvents) > eventsToSampleFromEachFile) cts.Cancel();
9695
lock (allActions) evt.Actions.Select(action => allActions.Add(action.Key)).Count();
9796
lock (allFields) evt.Fields.Select(field => allFields.Add(field.Key)).Count();
9897
return Task.CompletedTask;
9998
}, cts.Token);
10099
} catch (AggregateException e) {
101-
if (e.InnerException is OperationCanceledException) if (!internalCancel) return new Tuple<List<string>, List<string>>(new List<string>(), new List<string>());
102-
else throw;
103-
} catch (OperationCanceledException) { if (!internalCancel) return new Tuple<List<string>, List<string>>(new List<string>(), new List<string>()); }
100+
if (e.InnerException is not OperationCanceledException) throw;
101+
} catch (OperationCanceledException) { /* nothing to do, as cancel the operation at the end of sampling */ }
104102
}
105103

106104
return new Tuple<List<string>, List<string>>(allActions.OrderBy(k => k).ToList(), allFields.OrderBy(k => k).ToList());

GUI/MainForm.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,8 @@ private async void CallStackInput_DragDrop(object sender, DragEventArgs e) {
223223

224224
private async Task<List<string>> GetUserSelectedXEFieldsAsync(string[] fileNames) {
225225
using var fieldsListDialog = new FieldSelection();
226-
using var cts = new CancellationTokenSource();
227226
fieldsListDialog.Text = "Select relevant XEvent fields";
228-
var xeEventItems = await this._resolver.GetDistinctXELFieldsAsync(fileNames, 1000, cts);
227+
var xeEventItems = await this._resolver.GetDistinctXELFieldsAsync(fileNames, 1000);
229228
if (xeEventItems.Item1.Count + xeEventItems.Item2.Count == 0) return new List<string>();
230229
fieldsListDialog.AllActions = xeEventItems.Item1;
231230
fieldsListDialog.AllFields = xeEventItems.Item2;

Tests/Tests.cs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,7 @@ private string PrepareLargeXEventInput() {
305305

306306
[TestMethod][TestCategory("Unit")] public async Task XELActionsAndFieldsAsync() {
307307
using var csr = new StackResolver();
308-
using var cts = new CancellationTokenSource();
309-
var ret = await csr.GetDistinctXELFieldsAsync(new[] { @"..\..\..\Tests\TestCases\ImportXEL\xe_wait_completed_0_132353446563350000.xel" }, 1000, cts);
308+
var ret = await csr.GetDistinctXELFieldsAsync(new[] { @"..\..\..\Tests\TestCases\ImportXEL\xe_wait_completed_0_132353446563350000.xel" }, 5);
310309
Assert.AreEqual(1, ret.Item1.Count); // just the callstack action
311310
Assert.AreEqual("callstack", ret.Item1.First()); // verify the name
312311
Assert.AreEqual(5, ret.Item2.Count); // 5 fields
@@ -316,8 +315,7 @@ private string PrepareLargeXEventInput() {
316315

317316
[TestMethod][TestCategory("Unit")] public async Task XELActionsAndFieldsAsyncMultipleFiles() {
318317
using var csr = new StackResolver();
319-
using var cts = new CancellationTokenSource();
320-
var ret = await csr.GetDistinctXELFieldsAsync(new[] { @"..\..\..\Tests\TestCases\ImportXEL\xe_wait_completed_0_132353446563350000.xel", @"..\..\..\Tests\TestCases\ImportXEL\XESpins_0_131627061603030000.xel" }, 1000, cts);
318+
var ret = await csr.GetDistinctXELFieldsAsync(new[] { @"..\..\..\Tests\TestCases\ImportXEL\xe_wait_completed_0_132353446563350000.xel", @"..\..\..\Tests\TestCases\ImportXEL\XESpins_0_131627061603030000.xel" }, 5);
321319
Assert.AreEqual(1, ret.Item1.Count); // just the callstack action
322320
Assert.AreEqual("callstack", ret.Item1.First()); // verify the name
323321
Assert.AreEqual(9, ret.Item2.Count); // 9 fields in total across the 2 XEL files
@@ -776,15 +774,6 @@ private string PrepareLargeXEventInput() {
776774
Assert.AreEqual(0, xelTask.Result.Item1);
777775
Assert.AreEqual(StackResolver.OperationCanceled, xelTask.Result.Item2);
778776

779-
using var cts2 = new CancellationTokenSource();
780-
var xelFieldsTask = csr.GetDistinctXELFieldsAsync(new[] { @"..\..\..\Tests\TestCases\ImportXEL\XESpins_0_131627061603030000.xel" }, int.MaxValue, cts2);
781-
while (true) {
782-
if (xelFieldsTask.Wait(StackResolver.OperationWaitIntervalMilliseconds)) break;
783-
cts2.Cancel();
784-
}
785-
Assert.AreEqual(0, xelFieldsTask.Result.Item1.Count);
786-
Assert.AreEqual(0, xelFieldsTask.Result.Item2.Count);
787-
788777
Assert.IsTrue(csr.ProcessBaseAddresses(@"c:\mssql\binn\sqldk.dll 00000001`00400000"));
789778
var xeventInput = PrepareLargeXEventInput().ToString();
790779
using var cts3 = new CancellationTokenSource();

0 commit comments

Comments
 (0)