Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASM] Context disposed related exceptions when calling the WAF #6529

Merged
merged 13 commits into from
Jan 15, 2025

Conversation

NachoEchevarria
Copy link
Contributor

@NachoEchevarria NachoEchevarria commented Jan 10, 2025

Summary of changes

We are getting (on netcore only) some ObjectDisposedExceptions when calling the WAF.

Some stack examples:

System.ObjectDisposedException
at Microsoft.AspNetCore.Http.Features.FeatureReferences`1.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.DefaultHttpResponse.get_StatusCode()
at Datadog.Trace.AppSec.Coordinator.SecurityCoordinator.HttpTransport.get_StatusCode()
at Datadog.Trace.AppSec.Coordinator.SecurityCoordinator.RunWaf(Dictionary`2 args, Boolean lastWafCall, Boolean runWithEphemeral, Boolean isRasp)

System.ObjectDisposedException   
at Microsoft.AspNetCore.Http.Features.FeatureReferences`1.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.DefaultHttpContext.get_Items()
at Datadog.Trace.AppSec.Coordinator.SecurityCoordinator.HttpTransport.get_ReportedExternalWafsRequestHeaders()
at Datadog.Trace.AppSec.Coordinator.SecurityCoordinator.TryReport(IResult result, Boolean blocked, Nullable`1 status)
at Datadog.Trace.AppSec.Coordinator.SecurityCoordinator.ReportAndBlock(IResult result)

The number of orgs that suffer from it is small. It seems that we are tying to access the HttpContext after disposal. This launches an exception when trying to access the features of the context.

The method Uninitialize() of the class DefaultHttpContext is called when the request finishes:

    public void Uninitialize()
    {
        _features = default;
        _request.Uninitialize();
        _response.Uninitialize();
        _connection?.Uninitialize();
        _websockets?.Uninitialize();
        _active = false;
    }

public override IFeatureCollection Features => _features.Collection ?? ContextDisposed();

When we try to access some values from the context such as the return code, we eventually get this exception.

Why this could happen? Two possible explanations have been identified:

  1. Manual call to the method Uninitialize of DefaultHttpContext. While it's not commonly called, this method can be actually called from the controller because it's public.
  2. Racing conditions. If we launch some threads in a controller that, for instance, read files. RASP will try to call the WAF. These threads might be still running after the request has been closed. While RASP checks for closed spans, it could happen that RASP would call the WAF at the same time as the request and span closes.

If we detect that the context has been uninitialized, we should stop using it. Unfortunately, there is no reliable way to detect if the context is disposed before getting it's features. In the previous Uninitialize method, the field _active is private. We cannot get the features without getting the exception and the fields _response, _request, _connection and _websockets set their features to default, but these feature fields are not exposed. Given that, we can only capture the exception and assume that the context has been disposed and we should not try to access it anymore (or use reflection).

Some sample code has been added to our sample pages in order to reproduce the situation.

In .net framework, we are not getting these exceptions when trying to access the context with a similar code. This is consistent with the results got from the telemetry logs.

While we are accessing the context in several parts of our code, it seems that all the exceptions observed were thrown in the method RunWaf(). No other ObjectDisposed exception was found out of this scope so, for now, we are protecting only this part of the code.

The sample code that calls the manual uninitialization of the tracer would also make the Asp.Netcore framework to launch an exception after finishing the request. This exception prevents the tracer to close the root span.

Reason for change

Implementation details

Test coverage

Other details

@andrewlock
Copy link
Member

andrewlock commented Jan 10, 2025

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing the following branches/commits:

Execution-time benchmarks measure the whole time it takes to execute a program. And are intended to measure the one-off costs. Cases where the execution time results for the PR are worse than latest master results are shown in red. The following thresholds were used for comparing the execution times:

  • Welch test with statistical test for significance of 5%
  • Only results indicating a difference greater than 5% and 5 ms are considered.

Note that these results are based on a single point-in-time result for each branch. For full results, see the dashboard.

Graphs show the p99 interval based on the mean and StdDev of the test run, as well as the mean value of the run (shown as a diamond below the graph).

gantt
    title Execution time (ms) FakeDbCommand (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6529) - mean (69ms)  : 66, 71
     .   : milestone, 69,
    master - mean (69ms)  : 66, 72
     .   : milestone, 69,

    section CallTarget+Inlining+NGEN
    This PR (6529) - mean (978ms)  : 956, 1000
     .   : milestone, 978,
    master - mean (975ms)  : 950, 1001
     .   : milestone, 975,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6529) - mean (107ms)  : 104, 110
     .   : milestone, 107,
    master - mean (108ms)  : 105, 110
     .   : milestone, 108,

    section CallTarget+Inlining+NGEN
    This PR (6529) - mean (678ms)  : 665, 692
     .   : milestone, 678,
    master - mean (679ms)  : 664, 694
     .   : milestone, 679,

Loading
gantt
    title Execution time (ms) FakeDbCommand (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6529) - mean (91ms)  : 89, 93
     .   : milestone, 91,
    master - mean (91ms)  : 90, 93
     .   : milestone, 91,

    section CallTarget+Inlining+NGEN
    This PR (6529) - mean (634ms)  : 615, 653
     .   : milestone, 634,
    master - mean (635ms)  : 619, 651
     .   : milestone, 635,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Framework 4.6.2) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6529) - mean (190ms)  : 186, 195
     .   : milestone, 190,
    master - mean (194ms)  : 189, 198
     .   : milestone, 194,

    section CallTarget+Inlining+NGEN
    This PR (6529) - mean (1,088ms)  : 1067, 1110
     .   : milestone, 1088,
    master - mean (1,094ms)  : 1067, 1122
     .   : milestone, 1094,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET Core 3.1) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6529) - mean (275ms)  : 271, 279
     .   : milestone, 275,
    master - mean (277ms)  : 273, 281
     .   : milestone, 277,

    section CallTarget+Inlining+NGEN
    This PR (6529) - mean (865ms)  : 840, 890
     .   : milestone, 865,
    master - mean (871ms)  : 849, 892
     .   : milestone, 871,

Loading
gantt
    title Execution time (ms) HttpMessageHandler (.NET 6) 
    dateFormat  X
    axisFormat %s
    todayMarker off
    section Baseline
    This PR (6529) - mean (264ms)  : 261, 266
     .   : milestone, 264,
    master - mean (267ms)  : 263, 271
     .   : milestone, 267,

    section CallTarget+Inlining+NGEN
    This PR (6529) - mean (849ms)  : 817, 881
     .   : milestone, 849,
    master - mean (855ms)  : 820, 889
     .   : milestone, 855,

Loading

@datadog-ddstaging
Copy link

datadog-ddstaging bot commented Jan 10, 2025

Datadog Report

Branch report: nacho/ContextDisposedRelatedExceptions
Commit report: bd28929
Test service: dd-trace-dotnet

✅ 0 Failed, 242821 Passed, 1967 Skipped, 18h 52m 53.63s Total Time

@andrewlock
Copy link
Member

andrewlock commented Jan 10, 2025

Benchmarks Report for appsec 🐌

Benchmarks for #6529 compared to master:

  • All benchmarks have the same speed
  • 2 benchmarks have fewer allocations
  • 1 benchmarks have more allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.Asm.AppSecBodyBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net6.0 204μs 117ns 405ns 2.66 0 0 188.76 KB
master AllCycleSimpleBody netcoreapp3.1 296μs 194ns 725ns 2.65 0 0 196.09 KB
master AllCycleSimpleBody net472 275μs 280ns 1.08μs 35.8 2.05 0 225.79 KB
master AllCycleMoreComplexBody net6.0 215μs 75.6ns 283ns 2.65 0 0 192.26 KB
master AllCycleMoreComplexBody netcoreapp3.1 315μs 174ns 672ns 2.67 0 0 199.51 KB
master AllCycleMoreComplexBody net472 276μs 192ns 745ns 36.3 2.06 0 229.3 KB
master ObjectExtractorSimpleBody net6.0 148ns 0.1ns 0.375ns 0.00396 0 0 280 B
master ObjectExtractorSimpleBody netcoreapp3.1 196ns 0.206ns 0.77ns 0.00364 0 0 272 B
master ObjectExtractorSimpleBody net472 165ns 0.198ns 0.741ns 0.0446 0 0 281 B
master ObjectExtractorMoreComplexBody net6.0 2.91μs 1.78ns 6.68ns 0.0527 0 0 3.78 KB
master ObjectExtractorMoreComplexBody netcoreapp3.1 3.78μs 3.22ns 12ns 0.0509 0 0 3.69 KB
master ObjectExtractorMoreComplexBody net472 3.68μs 2.09ns 7.55ns 0.602 0.00552 0 3.8 KB
#6529 AllCycleSimpleBody net6.0 201μs 234ns 875ns 2.62 0 0 188.69 KB
#6529 AllCycleSimpleBody netcoreapp3.1 301μs 256ns 956ns 2.68 0 0 196.02 KB
#6529 AllCycleSimpleBody net472 268μs 219ns 849ns 35.8 2.02 0 225.75 KB
#6529 AllCycleMoreComplexBody net6.0 209μs 129ns 481ns 2.73 0 0 192.19 KB
#6529 AllCycleMoreComplexBody netcoreapp3.1 304μs 81ns 303ns 2.73 0 0 199.43 KB
#6529 AllCycleMoreComplexBody net472 278μs 311ns 1.16μs 36.4 2.07 0 229.27 KB
#6529 ObjectExtractorSimpleBody net6.0 144ns 0.11ns 0.396ns 0.00393 0 0 280 B
#6529 ObjectExtractorSimpleBody netcoreapp3.1 202ns 0.0977ns 0.365ns 0.00367 0 0 272 B
#6529 ObjectExtractorSimpleBody net472 169ns 0.111ns 0.416ns 0.0446 0 0 281 B
#6529 ObjectExtractorMoreComplexBody net6.0 2.88μs 1.26ns 4.89ns 0.0532 0 0 3.78 KB
#6529 ObjectExtractorMoreComplexBody netcoreapp3.1 3.85μs 2.7ns 9.72ns 0.0498 0 0 3.69 KB
#6529 ObjectExtractorMoreComplexBody net472 3.7μs 2.39ns 8.62ns 0.603 0.00552 0 3.8 KB
Benchmarks.Trace.Asm.AppSecEncoderBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EncodeArgs net6.0 37.4μs 21.8ns 78.5ns 0.443 0 0 32.4 KB
master EncodeArgs netcoreapp3.1 53.9μs 29.2ns 113ns 0.43 0 0 32.4 KB
master EncodeArgs net472 65.9μs 56.3ns 211ns 5.14 0.0654 0 32.5 KB
master EncodeLegacyArgs net6.0 78μs 22.2ns 83.1ns 0 0 0 2.14 KB
master EncodeLegacyArgs netcoreapp3.1 109μs 382ns 1.48μs 0 0 0 2.14 KB
master EncodeLegacyArgs net472 153μs 135ns 522ns 0.306 0 0 2.15 KB
#6529 EncodeArgs net6.0 37.4μs 36.8ns 138ns 0.464 0 0 32.4 KB
#6529 EncodeArgs netcoreapp3.1 53.8μs 23.2ns 90ns 0.454 0 0 32.4 KB
#6529 EncodeArgs net472 65.9μs 67.2ns 260ns 5.15 0.066 0 32.5 KB
#6529 EncodeLegacyArgs net6.0 71.8μs 36.7ns 142ns 0 0 0 2.14 KB
#6529 EncodeLegacyArgs netcoreapp3.1 106μs 425ns 1.65μs 0 0 0 2.14 KB
#6529 EncodeLegacyArgs net472 153μs 191ns 716ns 0.308 0 0 2.15 KB
Benchmarks.Trace.Asm.AppSecWafBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunWafRealisticBenchmark net6.0 176μs 118ns 458ns 0 0 0 2.44 KB
master RunWafRealisticBenchmark netcoreapp3.1 188μs 128ns 497ns 0 0 0 2.39 KB
master RunWafRealisticBenchmark net472 200μs 80.2ns 311ns 0.299 0 0 2.46 KB
master RunWafRealisticBenchmarkWithAttack net6.0 115μs 36.3ns 136ns 0 0 0 1.47 KB
master RunWafRealisticBenchmarkWithAttack netcoreapp3.1 123μs 212ns 794ns 0 0 0 1.46 KB
master RunWafRealisticBenchmarkWithAttack net472 134μs 54.8ns 212ns 0.2 0 0 1.49 KB
#6529 RunWafRealisticBenchmark net6.0 174μs 223ns 835ns 0 0 0 2.44 KB
#6529 RunWafRealisticBenchmark netcoreapp3.1 185μs 78.5ns 304ns 0 0 0 2.39 KB
#6529 RunWafRealisticBenchmark net472 201μs 80.6ns 302ns 0.301 0 0 2.46 KB
#6529 RunWafRealisticBenchmarkWithAttack net6.0 115μs 96.4ns 373ns 0 0 0 1.47 KB
#6529 RunWafRealisticBenchmarkWithAttack netcoreapp3.1 122μs 83ns 321ns 0 0 0 1.46 KB
#6529 RunWafRealisticBenchmarkWithAttack net472 132μs 51.1ns 184ns 0.197 0 0 1.49 KB
Benchmarks.Trace.Iast.StringAspectsBenchmark - Same speed ✔️ More allocations ⚠️

More allocations ⚠️ in #6529

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatBenchmark‑net472 59.07 KB 59.46 KB 392 B 0.66%

Fewer allocations 🎉 in #6529

Benchmark Base Allocated Diff Allocated Change Change %
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑netcoreapp3.1 255.27 KB 253.58 KB -1.69 KB -0.66%
Benchmarks.Trace.Iast.StringAspectsBenchmark.StringConcatAspectBenchmark‑net6.0 264.02 KB 255.85 KB -8.18 KB -3.10%

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StringConcatBenchmark net6.0 59.4μs 518ns 4.75μs 0 0 0 43.44 KB
master StringConcatBenchmark netcoreapp3.1 54μs 236ns 818ns 0 0 0 42.64 KB
master StringConcatBenchmark net472 38.5μs 174ns 651ns 0 0 0 59.07 KB
master StringConcatAspectBenchmark net6.0 308μs 1.36μs 5.11μs 0 0 0 264.02 KB
master StringConcatAspectBenchmark netcoreapp3.1 346μs 1.71μs 7.64μs 0 0 0 255.27 KB
master StringConcatAspectBenchmark net472 282μs 5.75μs 55.4μs 0 0 0 278.53 KB
#6529 StringConcatBenchmark net6.0 59.1μs 739ns 7.24μs 0 0 0 43.44 KB
#6529 StringConcatBenchmark netcoreapp3.1 54.6μs 300ns 1.72μs 0 0 0 42.64 KB
#6529 StringConcatBenchmark net472 37.7μs 182ns 706ns 0 0 0 59.46 KB
#6529 StringConcatAspectBenchmark net6.0 317μs 1.77μs 11.8μs 0 0 0 255.85 KB
#6529 StringConcatAspectBenchmark netcoreapp3.1 348μs 1.81μs 12μs 0 0 0 253.58 KB
#6529 StringConcatAspectBenchmark net472 299μs 7.06μs 69.6μs 0 0 0 278.53 KB

@andrewlock
Copy link
Member

andrewlock commented Jan 10, 2025

Benchmarks Report for tracer 🐌

Benchmarks for #6529 compared to master:

  • 1 benchmarks are faster, with geometric mean 1.117
  • 2 benchmarks are slower, with geometric mean 1.146
  • All benchmarks have the same allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.ActivityBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartStopWithChild net6.0 8.3μs 48.2ns 449ns 0.0137 0.00686 0 5.61 KB
master StartStopWithChild netcoreapp3.1 10.2μs 57ns 369ns 0.0205 0.0102 0 5.8 KB
master StartStopWithChild net472 16.2μs 40.1ns 155ns 1.05 0.306 0.0965 6.2 KB
#6529 StartStopWithChild net6.0 8.02μs 45.6ns 312ns 0.0154 0.00771 0 5.61 KB
#6529 StartStopWithChild netcoreapp3.1 10.3μs 54.1ns 265ns 0.0154 0.00512 0 5.8 KB
#6529 StartStopWithChild net472 16.6μs 58.5ns 227ns 1.06 0.332 0.105 6.21 KB
Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 501μs 243ns 940ns 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 669μs 684ns 2.56μs 0 0 0 2.7 KB
master WriteAndFlushEnrichedTraces net472 857μs 919ns 3.56μs 0.422 0 0 3.3 KB
#6529 WriteAndFlushEnrichedTraces net6.0 476μs 353ns 1.37μs 0 0 0 2.7 KB
#6529 WriteAndFlushEnrichedTraces netcoreapp3.1 646μs 371ns 1.44μs 0 0 0 2.7 KB
#6529 WriteAndFlushEnrichedTraces net472 856μs 702ns 2.63μs 0.428 0 0 3.3 KB
Benchmarks.Trace.AspNetCoreBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net6.0 164μs 1.34μs 13.3μs 0.145 0 0 14.48 KB
master SendRequest netcoreapp3.1 182μs 1.19μs 11.7μs 0.179 0 0 17.27 KB
master SendRequest net472 0.00798ns 0.00243ns 0.00908ns 0 0 0 0 b
#6529 SendRequest net6.0 148μs 827ns 5.16μs 0.141 0 0 14.47 KB
#6529 SendRequest netcoreapp3.1 168μs 879ns 7.66μs 0.168 0 0 17.27 KB
#6529 SendRequest net472 0.000375ns 0.000375ns 0.0014ns 0 0 0 0 b
Benchmarks.Trace.CIVisibilityProtocolWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net6.0 610μs 3.3μs 29.5μs 0.581 0 0 41.78 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 728μs 5.77μs 57.4μs 0.332 0 0 41.74 KB
master WriteAndFlushEnrichedTraces net472 874μs 3.54μs 13.2μs 8.08 2.55 0.425 53.34 KB
#6529 WriteAndFlushEnrichedTraces net6.0 575μs 2.08μs 7.78μs 0.573 0 0 41.72 KB
#6529 WriteAndFlushEnrichedTraces netcoreapp3.1 675μs 3.62μs 19.5μs 0.331 0 0 41.82 KB
#6529 WriteAndFlushEnrichedTraces net472 844μs 4.34μs 20.8μs 8.75 2.5 0.417 53.26 KB
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net6.0 1.31μs 1.55ns 5.99ns 0.0144 0 0 1.02 KB
master ExecuteNonQuery netcoreapp3.1 1.79μs 1.04ns 3.89ns 0.0133 0 0 1.02 KB
master ExecuteNonQuery net472 2.04μs 1.89ns 6.83ns 0.157 0.00102 0 987 B
#6529 ExecuteNonQuery net6.0 1.29μs 1.34ns 5.17ns 0.0142 0 0 1.02 KB
#6529 ExecuteNonQuery netcoreapp3.1 1.74μs 1.46ns 5.65ns 0.0138 0 0 1.02 KB
#6529 ExecuteNonQuery net472 2μs 2.24ns 8.69ns 0.156 0.00101 0 987 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net6.0 1.26μs 0.915ns 3.43ns 0.0133 0 0 976 B
master CallElasticsearch netcoreapp3.1 1.63μs 0.725ns 2.71ns 0.013 0 0 976 B
master CallElasticsearch net472 2.64μs 3.75ns 14.5ns 0.158 0 0 995 B
master CallElasticsearchAsync net6.0 1.34μs 0.935ns 3.62ns 0.0134 0 0 952 B
master CallElasticsearchAsync netcoreapp3.1 1.64μs 0.983ns 3.55ns 0.0135 0 0 1.02 KB
master CallElasticsearchAsync net472 2.68μs 3.01ns 11.7ns 0.167 0 0 1.05 KB
#6529 CallElasticsearch net6.0 1.14μs 0.502ns 1.95ns 0.0139 0 0 976 B
#6529 CallElasticsearch netcoreapp3.1 1.55μs 0.903ns 3.5ns 0.0132 0 0 976 B
#6529 CallElasticsearch net472 2.62μs 2.13ns 8.25ns 0.158 0 0 995 B
#6529 CallElasticsearchAsync net6.0 1.25μs 0.523ns 2.03ns 0.0132 0 0 952 B
#6529 CallElasticsearchAsync netcoreapp3.1 1.67μs 1.32ns 4.94ns 0.0135 0 0 1.02 KB
#6529 CallElasticsearchAsync net472 2.7μs 1.39ns 5.01ns 0.167 0 0 1.05 KB
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net6.0 1.3μs 1.03ns 3.85ns 0.0131 0 0 952 B
master ExecuteAsync netcoreapp3.1 1.56μs 1.28ns 4.62ns 0.0125 0 0 952 B
master ExecuteAsync net472 1.85μs 0.853ns 3.19ns 0.145 0 0 915 B
#6529 ExecuteAsync net6.0 1.31μs 0.744ns 2.88ns 0.0132 0 0 952 B
#6529 ExecuteAsync netcoreapp3.1 1.6μs 1.88ns 7.03ns 0.0128 0 0 952 B
#6529 ExecuteAsync net472 1.77μs 0.42ns 1.63ns 0.145 0 0 915 B
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net6.0 4.28μs 1.45ns 5.41ns 0.0323 0 0 2.31 KB
master SendAsync netcoreapp3.1 5.25μs 0.952ns 3.69ns 0.0368 0 0 2.85 KB
master SendAsync net472 7.29μs 2.21ns 8.27ns 0.495 0 0 3.12 KB
#6529 SendAsync net6.0 4.49μs 1.5ns 5.62ns 0.0335 0 0 2.31 KB
#6529 SendAsync netcoreapp3.1 5.19μs 2.78ns 10ns 0.0389 0 0 2.85 KB
#6529 SendAsync net472 7.45μs 2.7ns 10.4ns 0.494 0 0 3.12 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 1.52μs 0.698ns 2.7ns 0.0228 0 0 1.64 KB
master EnrichedLog netcoreapp3.1 2.28μs 1.05ns 3.93ns 0.0216 0 0 1.64 KB
master EnrichedLog net472 2.73μs 2.24ns 8.37ns 0.249 0 0 1.57 KB
#6529 EnrichedLog net6.0 1.47μs 1.08ns 4.17ns 0.0231 0 0 1.64 KB
#6529 EnrichedLog netcoreapp3.1 2.2μs 1.11ns 4.14ns 0.0227 0 0 1.64 KB
#6529 EnrichedLog net472 2.61μs 1.45ns 5.63ns 0.249 0 0 1.57 KB
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 119μs 180ns 699ns 0.0585 0 0 4.28 KB
master EnrichedLog netcoreapp3.1 120μs 132ns 510ns 0 0 0 4.28 KB
master EnrichedLog net472 151μs 167ns 645ns 0.68 0.227 0 4.46 KB
#6529 EnrichedLog net6.0 118μs 372ns 1.34μs 0.0583 0 0 4.28 KB
#6529 EnrichedLog netcoreapp3.1 121μs 147ns 571ns 0 0 0 4.28 KB
#6529 EnrichedLog net472 151μs 84.7ns 328ns 0.677 0.226 0 4.46 KB
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 2.9μs 0.932ns 3.61ns 0.0306 0 0 2.2 KB
master EnrichedLog netcoreapp3.1 4.25μs 2.47ns 9.57ns 0.0297 0 0 2.2 KB
master EnrichedLog net472 4.99μs 1.77ns 6.86ns 0.319 0 0 2.02 KB
#6529 EnrichedLog net6.0 3.01μs 1.45ns 5.41ns 0.0301 0 0 2.2 KB
#6529 EnrichedLog netcoreapp3.1 4.11μs 1.36ns 5.26ns 0.0284 0 0 2.2 KB
#6529 EnrichedLog net472 5.13μs 1.32ns 5.13ns 0.32 0 0 2.02 KB
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net6.0 1.38μs 1.35ns 5.03ns 0.0161 0 0 1.14 KB
master SendReceive netcoreapp3.1 1.76μs 0.909ns 3.52ns 0.015 0 0 1.14 KB
master SendReceive net472 2.06μs 1.62ns 6.29ns 0.183 0 0 1.16 KB
#6529 SendReceive net6.0 1.34μs 0.678ns 2.54ns 0.016 0 0 1.14 KB
#6529 SendReceive netcoreapp3.1 1.74μs 0.942ns 3.52ns 0.0149 0 0 1.14 KB
#6529 SendReceive net472 2.05μs 0.902ns 3.49ns 0.183 0 0 1.16 KB
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net6.0 2.65μs 0.845ns 3.16ns 0.0225 0 0 1.6 KB
master EnrichedLog netcoreapp3.1 3.9μs 1.33ns 5.15ns 0.0215 0 0 1.65 KB
master EnrichedLog net472 4.36μs 4.27ns 16ns 0.323 0 0 2.04 KB
#6529 EnrichedLog net6.0 2.64μs 1.21ns 4.7ns 0.0225 0 0 1.6 KB
#6529 EnrichedLog netcoreapp3.1 3.83μs 1.85ns 6.92ns 0.0211 0 0 1.65 KB
#6529 EnrichedLog net472 4.3μs 1.44ns 5.39ns 0.323 0 0 2.04 KB
Benchmarks.Trace.SpanBenchmark - Slower ⚠️ Same allocations ✔️

Slower ⚠️ in #6529

Benchmark diff/base Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net6.0 1.168 395.56 461.95
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net472 1.126 816.48 918.99

Faster 🎉 in #6529

Benchmark base/diff Base Median (ns) Diff Median (ns) Modality
Benchmarks.Trace.SpanBenchmark.StartFinishSpan‑net472 1.117 712.20 637.82

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net6.0 396ns 0.259ns 1ns 0.00804 0 0 576 B
master StartFinishSpan netcoreapp3.1 621ns 1.21ns 4.7ns 0.00773 0 0 576 B
master StartFinishSpan net472 712ns 0.333ns 1.29ns 0.0916 0 0 578 B
master StartFinishScope net6.0 466ns 0.212ns 0.766ns 0.00978 0 0 696 B
master StartFinishScope netcoreapp3.1 718ns 2.25ns 8.73ns 0.0094 0 0 696 B
master StartFinishScope net472 817ns 0.954ns 3.7ns 0.104 0 0 658 B
#6529 StartFinishSpan net6.0 462ns 0.194ns 0.726ns 0.0081 0 0 576 B
#6529 StartFinishSpan netcoreapp3.1 558ns 0.551ns 2.13ns 0.00781 0 0 576 B
#6529 StartFinishSpan net472 638ns 0.582ns 2.26ns 0.0917 0 0 578 B
#6529 StartFinishScope net6.0 476ns 0.387ns 1.5ns 0.00974 0 0 696 B
#6529 StartFinishScope netcoreapp3.1 750ns 0.288ns 1.12ns 0.00935 0 0 696 B
#6529 StartFinishScope net472 919ns 0.337ns 1.3ns 0.104 0 0 658 B
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net6.0 609ns 0.354ns 1.37ns 0.00974 0 0 696 B
master RunOnMethodBegin netcoreapp3.1 970ns 0.624ns 2.34ns 0.00962 0 0 696 B
master RunOnMethodBegin net472 1.12μs 0.636ns 2.46ns 0.104 0 0 658 B
#6529 RunOnMethodBegin net6.0 672ns 0.192ns 0.742ns 0.00971 0 0 696 B
#6529 RunOnMethodBegin netcoreapp3.1 895ns 0.419ns 1.62ns 0.00941 0 0 696 B
#6529 RunOnMethodBegin net472 1.1μs 1.58ns 6.12ns 0.104 0 0 658 B

@NachoEchevarria NachoEchevarria changed the title Nacho/context disposed related exceptions [ASM] Context disposed related exceptions when calling the WAF Jan 14, 2025
}
catch (ObjectDisposedException)
{
_contextUninitialized = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we could log here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@NachoEchevarria NachoEchevarria marked this pull request as ready for review January 14, 2025 10:41
@NachoEchevarria NachoEchevarria requested a review from a team as a code owner January 14, 2025 10:41
SecurityReporter.LogAddressIfDebugEnabled(args);
IResult? result = null;

try
{
var additiveContext = _httpTransport.GetAdditiveContext();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't the problem potentially still here? If the httpcontext is concurrently disposed right before calling GetAdditiveContext on l.60.. (and potentially on the SetAdditiveContext )
I'm wondering if the try catch shouldnt directly be in GetAdditiveContext of SecurityCoordinator.Core ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the context can be disposed at anytime while we use it. With this change, we are handling most of the errors that we are encountering, but it could happen what you just mentioned. On the other hand, checking for a disposed context anytime that we use it would have some performance impact and even that could not guarantee 100% that we are not getting more exceptions (if the context is disposed right after checking and before actually using it).

We could also try/catch any access to the context features (which includes almost every property associated to the context, request and response). In my first approach, I was doing that, but many code changes were required and, being practical, all the detected exceptions are happening in the same place, so I decided to protect just the problematic section. Do you think that try/catching any access to the context would be a better solution?

In the end, we probably will need to do a big refactor of our code to avoid accessing the context so often.

@NachoEchevarria NachoEchevarria merged commit 27f35a0 into master Jan 15, 2025
126 of 129 checks passed
@NachoEchevarria NachoEchevarria deleted the nacho/ContextDisposedRelatedExceptions branch January 15, 2025 17:24
@NachoEchevarria
Copy link
Contributor Author

Thank you for your feedback and reviews!

@github-actions github-actions bot added this to the vNext-v3 milestone Jan 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants