Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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>
Comment thread
ManickaP marked this conversation as resolved.
</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.
Comment thread
ManickaP marked this conversation as resolved.
Outdated
// The writing side is closed, the task is completed, and it will never get past this condition.
return valueTask.IsCompletedSuccessfully ?
Comment thread
ManickaP marked this conversation as resolved.
Outdated
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 thread
ManickaP marked this conversation as resolved.

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