Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit db2f033

Browse files
committed
Avoid allocating ExceptionDispatchInfo and ObjectDisposedException when disposing SslStream
SslStream uses its _exception to track whether the instance has been disposed, storing an ObjectDisposedException into it when disposal happens. We can instead just store a sentinel.
1 parent 98227f1 commit db2f033

File tree

1 file changed

+31
-26
lines changed
  • src/System.Net.Security/src/System/Net/Security

1 file changed

+31
-26
lines changed

src/System.Net.Security/src/System/Net/Security/SslState.cs

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,29 @@ internal SslState(Stream innerStream)
7777
_innerStream = innerStream;
7878
}
7979

80-
internal void ValidateCreateContext(SslClientAuthenticationOptions sslClientAuthenticationOptions)
80+
/// <summary>Set as the _exception when the instance is disposed.</summary>
81+
private static readonly ExceptionDispatchInfo s_disposedSentinel = ExceptionDispatchInfo.Capture(new ObjectDisposedException(nameof(SslStream)));
82+
83+
private void ThrowIfExceptional()
8184
{
82-
if (_exception != null)
85+
ExceptionDispatchInfo e = _exception;
86+
if (e != null)
8387
{
84-
_exception.Throw();
88+
// If the stored exception just indicates disposal, throw a new ODE rather than the stored one,
89+
// so as to not continually build onto the shared exception's stack.
90+
if (ReferenceEquals(e, s_disposedSentinel))
91+
{
92+
throw new ObjectDisposedException(nameof(SslStream));
93+
}
94+
95+
// Throw the stored exception.
96+
e.Throw();
8597
}
98+
}
99+
100+
internal void ValidateCreateContext(SslClientAuthenticationOptions sslClientAuthenticationOptions)
101+
{
102+
ThrowIfExceptional();
86103

87104
if (Context != null && Context.IsValidContext)
88105
{
@@ -118,10 +135,7 @@ internal void ValidateCreateContext(SslClientAuthenticationOptions sslClientAuth
118135

119136
internal void ValidateCreateContext(SslServerAuthenticationOptions sslServerAuthenticationOptions)
120137
{
121-
if (_exception != null)
122-
{
123-
_exception.Throw();
124-
}
138+
ThrowIfExceptional();
125139

126140
if (Context != null && Context.IsValidContext)
127141
{
@@ -401,7 +415,7 @@ internal int MaxDataSize
401415
}
402416
}
403417

404-
private ExceptionDispatchInfo SetException(Exception e)
418+
private void SetException(Exception e)
405419
{
406420
Debug.Assert(e != null, $"Expected non-null Exception to be passed to {nameof(SetException)}");
407421

@@ -410,12 +424,7 @@ private ExceptionDispatchInfo SetException(Exception e)
410424
_exception = ExceptionDispatchInfo.Capture(e);
411425
}
412426

413-
if (_exception != null && Context != null)
414-
{
415-
Context.Close();
416-
}
417-
418-
return _exception;
427+
Context?.Close();
419428
}
420429

421430
private bool HandshakeCompleted
@@ -436,10 +445,7 @@ private SecureChannel Context
436445

437446
internal void CheckThrow(bool authSuccessCheck, bool shutdownCheck = false)
438447
{
439-
if (_exception != null)
440-
{
441-
_exception.Throw();
442-
}
448+
ThrowIfExceptional();
443449

444450
if (authSuccessCheck && !IsAuthenticated)
445451
{
@@ -467,7 +473,7 @@ internal Task FlushAsync(CancellationToken cancellationToken)
467473
//
468474
internal void Close()
469475
{
470-
_exception = ExceptionDispatchInfo.Capture(new ObjectDisposedException(nameof(SslStream)));
476+
_exception = s_disposedSentinel;
471477
Context?.Close();
472478
_secureStream?.Dispose();
473479
}
@@ -666,14 +672,12 @@ private void ForceAuthentication(bool receiveFirst, byte[] buffer, AsyncProtocol
666672
_Framing = Framing.Unknown;
667673
_handshakeCompleted = false;
668674

669-
if (SetException(e).SourceException == e)
675+
SetException(e);
676+
if (_exception.SourceException != e)
670677
{
671-
throw;
672-
}
673-
else
674-
{
675-
_exception.Throw();
678+
ThrowIfExceptional();
676679
}
680+
throw;
677681
}
678682
finally
679683
{
@@ -732,7 +736,8 @@ internal void InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
732736
_Framing = Framing.Unknown;
733737
_handshakeCompleted = false;
734738

735-
SetException(e).Throw();
739+
SetException(e);
740+
ThrowIfExceptional();
736741
}
737742
}
738743

0 commit comments

Comments
 (0)