Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into wasm-workloads-staging
Browse files Browse the repository at this point in the history
  • Loading branch information
radical committed Jul 8, 2021
2 parents acd7740 + b877bcd commit 76cd866
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 42 deletions.
2 changes: 1 addition & 1 deletion eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Uri>https://github.com/dotnet/icu</Uri>
<Sha>e7626ad8c04b150de635f920b5e8dede0aafaf73</Sha>
</Dependency>
<Dependency Name="System.Net.MsQuic.Transport" Version="6.0.0-preview.7.21328.2">
<Dependency Name="System.Net.MsQuic.Transport" Version="6.0.0-preview.7.21357.1">
<Uri>https://github.com/dotnet/msquic</Uri>
<Sha>d7db669b70f4dd67ec001c192f9809c218cab88b</Sha>
</Dependency>
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
<!-- ICU -->
<MicrosoftNETCoreRuntimeICUTransportVersion>6.0.0-preview.7.21328.1</MicrosoftNETCoreRuntimeICUTransportVersion>
<!-- MsQuic -->
<SystemNetMsQuicTransportVersion>6.0.0-preview.7.21328.2</SystemNetMsQuicTransportVersion>
<SystemNetMsQuicTransportVersion>6.0.0-preview.7.21357.1</SystemNetMsQuicTransportVersion>
<!-- Mono LLVM -->
<runtimelinuxarm64MicrosoftNETCoreRuntimeMonoLLVMSdkVersion>11.1.0-alpha.1.21328.1</runtimelinuxarm64MicrosoftNETCoreRuntimeMonoLLVMSdkVersion>
<runtimelinuxarm64MicrosoftNETCoreRuntimeMonoLLVMToolsVersion>11.1.0-alpha.1.21328.1</runtimelinuxarm64MicrosoftNETCoreRuntimeMonoLLVMToolsVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public void RemoveStream(MsQuicStream? stream)
if (releaseHandles)
{
Handle?.Dispose();
StateGCHandle.Free();
}
}

Expand Down Expand Up @@ -235,19 +234,22 @@ private static uint HandleEventShutdownInitiatedByTransport(State state, ref Con
state.ConnectTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex));
}

state.AcceptQueue.Writer.Complete();
state.AcceptQueue.Writer.TryComplete();
return MsQuicStatusCodes.Success;
}

private static uint HandleEventShutdownInitiatedByPeer(State state, ref ConnectionEvent connectionEvent)
{
state.AbortErrorCode = (long)connectionEvent.Data.ShutdownInitiatedByPeer.ErrorCode;
state.AcceptQueue.Writer.Complete();
state.AcceptQueue.Writer.TryComplete();
return MsQuicStatusCodes.Success;
}

private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent connectionEvent)
{
// This is the final event on the connection, so free the GCHandle used by the event callback.
state.StateGCHandle.Free();

state.Connection = null;

state.ShutdownTcs.SetResult(MsQuicStatusCodes.Success);
Expand Down Expand Up @@ -533,6 +535,8 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d
_ => throw new Exception(SR.Format(SR.net_quic_unsupported_address_family, _remoteEndPoint.AddressFamily))
};

Debug.Assert(_state.StateGCHandle.IsAllocated);

_state.Connection = this;
try
{
Expand All @@ -547,6 +551,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d
}
catch
{
_state.StateGCHandle.Free();
_state.Connection = null;
throw;
}
Expand Down Expand Up @@ -593,7 +598,10 @@ private static uint NativeCallbackHandler(
IntPtr context,
ref ConnectionEvent connectionEvent)
{
var state = (State)GCHandle.FromIntPtr(context).Target!;
GCHandle gcHandle = GCHandle.FromIntPtr(context);
Debug.Assert(gcHandle.IsAllocated);
Debug.Assert(gcHandle.Target is not null);
var state = (State)gcHandle.Target;

if (NetEventSource.Log.IsEnabled())
{
Expand Down Expand Up @@ -626,9 +634,11 @@ private static uint NativeCallbackHandler(
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Error(state, $"[Connection#{state.GetHashCode()}] Exception occurred during handling {connectionEvent.Type} connection callback: {ex.Message}");
NetEventSource.Error(state, $"[Connection#{state.GetHashCode()}] Exception occurred during handling {connectionEvent.Type} connection callback: {ex}");
}

Debug.Fail($"[Connection#{state.GetHashCode()}] Exception occurred during handling {connectionEvent.Type} connection callback: {ex}");

// TODO: trigger an exception on any outstanding async calls.

return MsQuicStatusCodes.InternalError;
Expand Down Expand Up @@ -692,7 +702,6 @@ private void Dispose(bool disposing)
{
// We may not be fully initialized if constructor fails.
_state.Handle?.Dispose();
if (_state.StateGCHandle.IsAllocated) _state.StateGCHandle.Free();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Quic.Implementations.MsQuic.Internal;
using System.Net.Security;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -59,7 +60,6 @@ internal MsQuicListener(QuicListenerOptions options)
}
catch
{
_state.Handle?.Dispose();
_stateHandle.Free();
throw;
}
Expand Down Expand Up @@ -109,7 +109,15 @@ private void Dispose(bool disposing)

Stop();
_state?.Handle?.Dispose();

// Note that it's safe to free the state GCHandle here, because:
// (1) We called ListenerStop above, which will block until all listener events are processed. So we will not receive any more listener events.
// (2) This class is finalizable, which means we will always get called even if the user doesn't explicitly Dispose us.
// If we ever change this class to not be finalizable, and instead rely on the SafeHandle finalization, then we will need to make
// the SafeHandle responsible for freeing this GCHandle, since it will have the only chance to do so when finalized.

if (_stateHandle.IsAllocated) _stateHandle.Free();

_state?.ConnectionConfiguration?.Dispose();
_disposed = true;
}
Expand All @@ -123,13 +131,20 @@ private unsafe IPEndPoint Start(QuicListenerOptions options)

uint status;

Debug.Assert(_stateHandle.IsAllocated);

MemoryHandle[]? handles = null;
QuicBuffer[]? buffers = null;
try
{
MsQuicAlpnHelper.Prepare(applicationProtocols, out handles, out buffers);
status = MsQuicApi.Api.ListenerStartDelegate(_state.Handle, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)applicationProtocols.Count, ref address);
}
catch
{
_stateHandle.Free();
throw;
}
finally
{
MsQuicAlpnHelper.Return(ref handles, ref buffers);
Expand Down Expand Up @@ -167,7 +182,11 @@ private static unsafe uint NativeCallbackHandler(
return MsQuicStatusCodes.InternalError;
}

State state = (State)GCHandle.FromIntPtr(context).Target!;
GCHandle gcHandle = GCHandle.FromIntPtr(context);
Debug.Assert(gcHandle.IsAllocated);
Debug.Assert(gcHandle.Target is not null);
var state = (State)gcHandle.Target;

SafeMsQuicConnectionHandle? connectionHandle = null;

try
Expand Down Expand Up @@ -197,6 +216,13 @@ private static unsafe uint NativeCallbackHandler(
}
catch (Exception ex)
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {(QUIC_LISTENER_EVENT)evt.Type} connection callback: {ex}");
}

Debug.Fail($"[Listener#{state.GetHashCode()}] Exception occurred during handling {(QUIC_LISTENER_EVENT)evt.Type} connection callback: {ex}");

// This handle will be cleaned up by MsQuic by returning InternalError.
connectionHandle?.SetHandleAsInvalid();
state.AcceptConnectionQueue.Writer.TryComplete(ex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,11 @@ private static uint NativeCallbackHandler(
IntPtr context,
ref StreamEvent streamEvent)
{
var state = (State)GCHandle.FromIntPtr(context).Target!;
GCHandle gcHandle = GCHandle.FromIntPtr(context);
Debug.Assert(gcHandle.IsAllocated);
Debug.Assert(gcHandle.Target is not null);
var state = (State)gcHandle.Target;

return HandleEvent(state, ref streamEvent);
}

Expand Down Expand Up @@ -746,9 +750,13 @@ private static uint HandleEvent(State state, ref StreamEvent evt)
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Error(state, $"[Stream#{state.GetHashCode()}] Exception occurred during handling {(QUIC_STREAM_EVENT_TYPE)evt.Type} event: {ex.Message}");
NetEventSource.Error(state, $"[Stream#{state.GetHashCode()}] Exception occurred during handling {(QUIC_STREAM_EVENT_TYPE)evt.Type} event: {ex}");
}

// This is getting hit currently
// See https://github.com/dotnet/runtime/issues/55302
//Debug.Fail($"[Stream#{state.GetHashCode()}] Exception occurred during handling {(QUIC_STREAM_EVENT_TYPE)evt.Type} event: {ex}");

return MsQuicStatusCodes.InternalError;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ public async Task TestConnect()
Assert.Equal(ApplicationProtocol.ToString(), serverConnection.NegotiatedApplicationProtocol.ToString());
}

// this started to fail after updating msquic from cc104e836a5d4a5e0d324bc08b42136d2acac997 to 8e21db733f22533a613d404d2a86e64588019132
[ActiveIssue("https://github.com/dotnet/runtime/issues/49157")]
[Fact]
public async Task AcceptStream_ConnectionAborted_ByClient_Throws()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,7 @@ private static bool DirectoryExists(string fullPath)
{
Interop.Sys.FileStatus fileinfo;

// First use stat, as we want to follow symlinks. If that fails, it could be because the symlink
// is broken, we don't have permissions, etc., in which case fall back to using LStat to evaluate
// based on the symlink itself.
if (Interop.Sys.Stat(fullPath, out fileinfo) < 0 &&
Interop.Sys.LStat(fullPath, out fileinfo) < 0)
if (Interop.Sys.Stat(fullPath, out fileinfo) < 0)
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,55 @@ public static bool DirectoryExists(ReadOnlySpan<char> fullPath)

private static bool DirectoryExists(ReadOnlySpan<char> fullPath, out Interop.ErrorInfo errorInfo)
{
return FileExists(fullPath, Interop.Sys.FileTypes.S_IFDIR, out errorInfo);
Interop.Sys.FileStatus fileinfo;
errorInfo = default(Interop.ErrorInfo);

if (Interop.Sys.Stat(fullPath, out fileinfo) < 0)
{
errorInfo = Interop.Sys.GetLastErrorInfo();
return false;
}

return (fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
}

public static bool FileExists(ReadOnlySpan<char> fullPath)
{
Interop.ErrorInfo ignored;
return FileExists(fullPath, out ignored);
}

private static bool FileExists(ReadOnlySpan<char> fullPath, out Interop.ErrorInfo errorInfo)
{
Interop.Sys.FileStatus fileinfo;
errorInfo = default(Interop.ErrorInfo);

// File.Exists() explicitly checks for a trailing separator and returns false if found. FileInfo.Exists and all other
// internal usages do not check for the trailing separator. Historically we've always removed the trailing separator
// when getting attributes as trailing separators are generally not accepted by Windows APIs. Unix will take
// trailing separators, but it infers that the path must be a directory (it effectively appends "."). To align with
// our historical behavior (outside of File.Exists()), we need to trim.
//
// See http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap04.html#tag_04_11 for details.
return FileExists(Path.TrimEndingDirectorySeparator(fullPath), Interop.Sys.FileTypes.S_IFREG, out ignored);
}
fullPath = Path.TrimEndingDirectorySeparator(fullPath);

private static bool FileExists(ReadOnlySpan<char> fullPath, int fileType, out Interop.ErrorInfo errorInfo)
{
Debug.Assert(fileType == Interop.Sys.FileTypes.S_IFREG || fileType == Interop.Sys.FileTypes.S_IFDIR);

Interop.Sys.FileStatus fileinfo;
errorInfo = default(Interop.ErrorInfo);

// First use stat, as we want to follow symlinks. If that fails, it could be because the symlink
// is broken, we don't have permissions, etc., in which case fall back to using LStat to evaluate
// based on the symlink itself.
if (Interop.Sys.Stat(fullPath, out fileinfo) < 0 &&
Interop.Sys.LStat(fullPath, out fileinfo) < 0)
if (Interop.Sys.LStat(fullPath, out fileinfo) < 0)
{
errorInfo = Interop.Sys.GetLastErrorInfo();
return false;
}

// Something exists at this path. If the caller is asking for a directory, return true if it's
// a directory and false for everything else. If the caller is asking for a file, return false for
// a directory and true for everything else.
return
(fileType == Interop.Sys.FileTypes.S_IFDIR) ==
((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR);
// Something exists at this path. Return false for a directory and true for everything else.
// When the path is a link, get its target info.
if ((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK)
{
if (Interop.Sys.Stat(fullPath, out fileinfo) < 0)
{
return true;
}
}

return (fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) != Interop.Sys.FileTypes.S_IFDIR;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ public static void DeleteFile(string fullPath)

// Input allows trailing separators in order to match Windows behavior
// Unix does not accept trailing separators, so must be trimmed
if (!FileExists(Path.TrimEndingDirectorySeparator(fullPath),
Interop.Sys.FileTypes.S_IFREG, out fileExistsError) &&
if (!FileExists(fullPath, out fileExistsError) &&
fileExistsError.Error == Interop.Error.ENOENT)
{
return;
Expand Down

0 comments on commit 76cd866

Please sign in to comment.