Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/libraries/System.Net.Quic/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@
<data name="net_auth_tls_alert" xml:space="preserve">
<value>Authentication failed because the remote party sent a TLS alert: '{0}'.</value>
</data>
<data name="net_writecompleted_invalidcall" xml:space="preserve">
<value>This method may not be called when writing side was already completed.</value>
</data>
<!-- Referenced in shared IPEndPointExtensions.cs -->
<data name="net_InvalidAddressFamily" xml:space="preserve">
<value>The AddressFamily {0} is not valid for the {1} end point, use {2} instead.</value>
Expand All @@ -240,4 +243,3 @@
<value>Authentication failed because the platform does not support ephemeral keys.</value>
</data>
</root>

Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public ResettableValueTaskSource()
public Action<object?> CancellationAction { init { _cancellationAction = value; } }

/// <summary>
/// Returns <c>true</c> is this task source has entered its final state, i.e. <see cref="TrySetResult(bool)"/> or <see cref="TrySetException(Exception)"/>
/// Returns <c>true</c> if this task source has entered its final state, i.e. <see cref="TrySetResult(bool)"/> or <see cref="TrySetException(Exception)"/>
/// was called with <c>final</c> set to <c>true</c> and the result was propagated.
/// </summary>
public bool IsCompleted => (State)Volatile.Read(ref Unsafe.As<State, byte>(ref _state)) == State.Completed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ public ValueTaskSource()
}

/// <summary>
/// Returns <c>true</c> is this task source was completed, i.e. <see cref="TrySetResult"/> or <see cref="TrySetException(Exception)"/> was called.
/// Returns <c>true</c> if this task source was completed, i.e. <see cref="TrySetResult"/> or <see cref="TrySetException(Exception)"/> was called.
/// </summary>
public bool IsCompleted => (State)Volatile.Read(ref Unsafe.As<State, byte>(ref _state)) == State.Completed;
/// <summary>
/// Returns <c>true</c> is this task source was completed successfully, i.e. <see cref="TrySetResult"/> was called and set the result.
/// Returns <c>true</c> if this task source was completed successfully, i.e. <see cref="TrySetResult"/> was called and set the result.
/// </summary>
public bool IsCompletedSuccessfully => IsCompleted && _valueTaskSource.GetStatus(_valueTaskSource.Version) == ValueTaskSourceStatus.Succeeded;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,11 @@ public ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, bool completeWrites, Ca
// No need to call anything since we already have a result, most likely an exception.
if (valueTask.IsCompleted)
{
return valueTask;
// It doesn't matter that we throw away the valueTask here, it doesn't need to be reset anymore.
// The writing side is closed, the task is completed, and it will never get past this condition.
return valueTask.IsCompletedSuccessfully ?
Comment on lines +423 to +425
ValueTask.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(new InvalidOperationException(SR.net_writecompleted_invalidcall))) :
valueTask;
}

// For an empty buffer complete immediately, close the writing side of the stream if necessary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,33 @@ await RunBidirectionalClientServer(
});
}

[Fact]
public async Task WritesCompleted_WritesAsync_Throws()
{
SemaphoreSlim sem = new SemaphoreSlim(0);
await RunBidirectionalClientServer(
async clientStream =>
{
// Close and wait for write completion.
clientStream.CompleteWrites();
await clientStream.WritesClosed;

// These both should throw the same exception.
await Assert.ThrowsAsync<InvalidOperationException>(async () => await clientStream.WriteAsync(new byte[0], false));
await Assert.ThrowsAsync<InvalidOperationException>(async () => await clientStream.WriteAsync(new byte[0], false));
Comment on lines +800 to +802

await sem.WaitAsync();
},
async serverStream =>
{
int received = await serverStream.ReadAsync(new byte[1]);
Assert.Equal(0, received);
await serverStream.ReadsClosed;

sem.Release();
});
}

[Fact]
public async Task WaitForWritesClosedAsync_ServerWriteAborted_Throws()
{
Expand Down
Loading