Skip to content

Commit e47cbf6

Browse files
shirhattiNGloreous
andauthored
[release/5.0] DelegationRule.Dispose() unsets delegation property on the queue (#28514)
* Unset delegation propery from source queue. This removes the process from the target URL group and allows the delegation rule to be added back later on in the processes lifetime * Add test * Add disposing pattern Co-authored-by: Nolan Glore <[email protected]>
1 parent 8a3c865 commit e47cbf6

File tree

4 files changed

+60
-4
lines changed

4 files changed

+60
-4
lines changed

src/Servers/HttpSys/src/DelegationRule.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys
1313
public class DelegationRule : IDisposable
1414
{
1515
private readonly ILogger _logger;
16+
private readonly UrlGroup _sourceQueueUrlGroup;
17+
private bool _disposed;
1618
/// <summary>
1719
/// The name of the Http.Sys request queue
1820
/// </summary>
@@ -23,8 +25,9 @@ public class DelegationRule : IDisposable
2325
public string UrlPrefix { get; }
2426
internal RequestQueue Queue { get; }
2527

26-
internal DelegationRule(string queueName, string urlPrefix, ILogger logger)
28+
internal DelegationRule(UrlGroup sourceQueueUrlGroup, string queueName, string urlPrefix, ILogger logger)
2729
{
30+
_sourceQueueUrlGroup = sourceQueueUrlGroup;
2831
_logger = logger;
2932
QueueName = queueName;
3033
UrlPrefix = urlPrefix;
@@ -34,8 +37,20 @@ internal DelegationRule(string queueName, string urlPrefix, ILogger logger)
3437
/// <inheritdoc />
3538
public void Dispose()
3639
{
37-
Queue.UrlGroup?.Dispose();
38-
Queue?.Dispose();
40+
if (_disposed)
41+
{
42+
return;
43+
}
44+
45+
_disposed = true;
46+
47+
try
48+
{
49+
_sourceQueueUrlGroup.UnSetDelegationProperty(Queue, throwOnError: false);
50+
}
51+
catch (ObjectDisposedException) { /* Server may have been shutdown */ }
52+
Queue.UrlGroup.Dispose();
53+
Queue.Dispose();
3954
}
4055
}
4156
}

src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ internal unsafe void SetDelegationProperty(RequestQueue destination)
8383
SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerDelegationProperty, new IntPtr(&propertyInfo), (uint)RequestPropertyInfoSize);
8484
}
8585

86+
internal unsafe void UnSetDelegationProperty(RequestQueue destination, bool throwOnError = true)
87+
{
88+
var propertyInfo = new HttpApiTypes.HTTP_BINDING_INFO();
89+
propertyInfo.Flags = HttpApiTypes.HTTP_FLAGS.NONE;
90+
propertyInfo.RequestQueueHandle = destination.Handle.DangerousGetHandle();
91+
92+
SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerDelegationProperty, new IntPtr(&propertyInfo), (uint)RequestPropertyInfoSize, throwOnError);
93+
}
94+
8695
internal void SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY property, IntPtr info, uint infosize, bool throwOnError = true)
8796
{
8897
Debug.Assert(info != IntPtr.Zero, "SetUrlGroupProperty called with invalid pointer");

src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public ServerDelegationPropertyFeature(RequestQueue queue, ILogger logger)
2121

2222
public DelegationRule CreateDelegationRule(string queueName, string uri)
2323
{
24-
var rule = new DelegationRule(queueName, uri, _logger);
24+
var rule = new DelegationRule(_queue.UrlGroup, queueName, uri, _logger);
2525
_queue.UrlGroup.SetDelegationProperty(rule.Queue);
2626
return rule;
2727
}

src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,38 @@ public async Task DelegationFeaturesAreNull()
161161
_ = await SendRequestAsync(delegatorAddress);
162162
}
163163

164+
[ConditionalFact]
165+
[DelegateSupportedCondition(true)]
166+
public async Task UpdateDelegationRuleTest()
167+
{
168+
var queueName = Guid.NewGuid().ToString();
169+
using var receiver = Utilities.CreateHttpServer(out var receiverAddress, async httpContext =>
170+
{
171+
await httpContext.Response.WriteAsync(_expectedResponseString);
172+
},
173+
options =>
174+
{
175+
options.RequestQueueName = queueName;
176+
});
177+
178+
DelegationRule destination = default;
179+
180+
using var delegator = Utilities.CreateHttpServer(out var delegatorAddress, httpContext =>
181+
{
182+
var delegateFeature = httpContext.Features.Get<IHttpSysRequestDelegationFeature>();
183+
delegateFeature.DelegateRequest(destination);
184+
return Task.CompletedTask;
185+
});
186+
187+
var delegationProperty = delegator.Features.Get<IServerDelegationFeature>();
188+
destination = delegationProperty.CreateDelegationRule(queueName, receiverAddress);
189+
destination?.Dispose();
190+
destination = delegationProperty.CreateDelegationRule(queueName, receiverAddress);
191+
var responseString = await SendRequestAsync(delegatorAddress);
192+
Assert.Equal(_expectedResponseString, responseString);
193+
destination?.Dispose();
194+
}
195+
164196
private async Task<string> SendRequestAsync(string uri)
165197
{
166198
using var client = new HttpClient();

0 commit comments

Comments
 (0)