Skip to content

Commit a179256

Browse files
authored
make async name resolution working from impersonificated context (#46897)
1 parent 8ba7866 commit a179256

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

Diff for: src/libraries/System.Net.NameResolution/src/System/Net/Dns.cs

+33-12
Original file line numberDiff line numberDiff line change
@@ -464,15 +464,22 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR
464464
{
465465
ValidateHostName(hostName);
466466

467+
Task? t;
467468
if (NameResolutionTelemetry.Log.IsEnabled())
468469
{
469-
return justAddresses
470-
? (Task)GetAddrInfoWithTelemetryAsync<IPAddress[]>(hostName, justAddresses)
471-
: (Task)GetAddrInfoWithTelemetryAsync<IPHostEntry>(hostName, justAddresses);
470+
t = justAddresses
471+
? (Task?)GetAddrInfoWithTelemetryAsync<IPAddress[]>(hostName, justAddresses)
472+
: (Task?)GetAddrInfoWithTelemetryAsync<IPHostEntry>(hostName, justAddresses);
472473
}
473474
else
474475
{
475-
return NameResolutionPal.GetAddrInfoAsync(hostName, justAddresses);
476+
t = NameResolutionPal.GetAddrInfoAsync(hostName, justAddresses);
477+
}
478+
479+
// If async resolution started, return task to user. otherwise fall back to sync API on threadpool.
480+
if (t != null)
481+
{
482+
return t;
476483
}
477484
}
478485

@@ -481,20 +488,34 @@ private static Task GetHostEntryOrAddressesCoreAsync(string hostName, bool justR
481488
RunAsync(s => GetHostEntryCore((string)s), hostName);
482489
}
483490

484-
private static async Task<T> GetAddrInfoWithTelemetryAsync<T>(string hostName, bool justAddresses)
491+
private static Task<T>? GetAddrInfoWithTelemetryAsync<T>(string hostName, bool justAddresses)
485492
where T : class
486493
{
487-
ValueStopwatch stopwatch = NameResolutionTelemetry.Log.BeforeResolution(hostName);
494+
ValueStopwatch stopwatch = ValueStopwatch.StartNew();
495+
Task? task = NameResolutionPal.GetAddrInfoAsync(hostName, justAddresses);
488496

489-
T? result = null;
490-
try
497+
if (task != null)
491498
{
492-
result = await ((Task<T>)NameResolutionPal.GetAddrInfoAsync(hostName, justAddresses)).ConfigureAwait(false);
493-
return result;
499+
return CompleteAsync(task, hostName, stopwatch);
494500
}
495-
finally
501+
502+
// If resolution even did not start don't bother with telemetry.
503+
// We will retry on thread-pool.
504+
return null;
505+
506+
static async Task<T> CompleteAsync(Task task, string hostName, ValueStopwatch stopwatch)
496507
{
497-
NameResolutionTelemetry.Log.AfterResolution(stopwatch, successful: result is not null);
508+
_ = NameResolutionTelemetry.Log.BeforeResolution(hostName);
509+
T? result = null;
510+
try
511+
{
512+
result = await ((Task<T>)task).ConfigureAwait(false);
513+
return result;
514+
}
515+
finally
516+
{
517+
NameResolutionTelemetry.Log.AfterResolution(stopwatch, successful: result is not null);
518+
}
498519
}
499520
}
500521

Diff for: src/libraries/System.Net.NameResolution/src/System/Net/NameResolutionPal.Windows.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public static unsafe string GetHostName()
141141
return new string((sbyte*)buffer);
142142
}
143143

144-
public static unsafe Task GetAddrInfoAsync(string hostName, bool justAddresses)
144+
public static unsafe Task? GetAddrInfoAsync(string hostName, bool justAddresses)
145145
{
146146
GetAddrInfoExContext* context = GetAddrInfoExContext.AllocateContext();
147147

@@ -166,7 +166,18 @@ public static unsafe Task GetAddrInfoAsync(string hostName, bool justAddresses)
166166
SocketError errorCode = (SocketError)Interop.Winsock.GetAddrInfoExW(
167167
hostName, null, Interop.Winsock.NS_ALL, IntPtr.Zero, &hints, &context->Result, IntPtr.Zero, &context->Overlapped, s_getAddrInfoExCallback, &context->CancelHandle);
168168

169-
if (errorCode != SocketError.IOPending)
169+
170+
if (errorCode == SocketError.TryAgain)
171+
{
172+
// WSATRY_AGAIN indicates possible problem with reachability according to docs.
173+
// However, if servers are really unreachable, we would still get IOPending here
174+
// and final result would be posted via overlapped IO.
175+
// synchronous failure here may signal issue when GetAddrInfoExW does not work from
176+
// impersonated context.
177+
GetAddrInfoExContext.FreeContext(context);
178+
return null;
179+
}
180+
else if (errorCode != SocketError.IOPending)
170181
{
171182
ProcessResult(errorCode, context);
172183
}

0 commit comments

Comments
 (0)