Repository: dotnet/runtime
File: src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs (C#)

Code before:
            }

            if (_internalBuffer == null)
            {
                // Suppress finalizer if the read buffer was returned.
                GC.SuppressFinalize(this);
            }
        }

        private SecurityStatusPal EncryptData(ReadOnlyMemory<byte> buffer, ref byte[] outBuffer, out int outSize)
        {
            ThrowIfExceptionalOrNotAuthenticated();

            TaskCompletionSource<bool>? waiter = null;
            while (true)
            {
                if (waiter != null)
                {
                    waiter.Task.Wait();
                    _handshakeWaiter = null;
                }

                lock (_handshakeLock)
                {
                    waiter = _handshakeWaiter;
                    if (_handshakeWaiter != null)
                    {
                        // avoid waiting under lock.
                        continue;
                    }

                    var ret = _context!.Encrypt(buffer, ref outBuffer, out outSize);
                    return ret;
                }
            }
        }

        private SecurityStatusPal DecryptData()
        {
            ThrowIfExceptionalOrNotAuthenticated();
            return PrivateDecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount);
        }

        private SecurityStatusPal PrivateDecryptData(byte[]? buffer, ref int offset, ref int count)
        {
            return _context!.Decrypt(buffer, ref offset, ref count);
        }

        //
        // This method assumes that a SSPI context is already in a good shape.
        // For example it is either a fresh context or already authenticated context that needs renegotiation.

Review comment (suggestion):
```suggestion
                    if (waiter != null)
```

Code after:
            }

            if (_internalBuffer == null)
            {
                // Suppress finalizer if the read buffer was returned.
                GC.SuppressFinalize(this);
            }
        }

        private SecurityStatusPal EncryptData(ReadOnlyMemory<byte> buffer, ref byte[] outBuffer, out int outSize)
        {
            ThrowIfExceptionalOrNotAuthenticated();

            lock (_handshakeLock)
            {
                if (_handshakeWaiter != null)
                {
                    outSize = 0;
                    // avoid waiting under lock.
                    return new SecurityStatusPal(SecurityStatusPalErrorCode.TryAgain);
                }

                return _context!.Encrypt(buffer, ref outBuffer, out outSize);
            }
        }

        private SecurityStatusPal DecryptData()
        {
            ThrowIfExceptionalOrNotAuthenticated();
            return PrivateDecryptData(_internalBuffer, ref _decryptedBytesOffset, ref _decryptedBytesCount);
        }

        private SecurityStatusPal PrivateDecryptData(byte[]? buffer, ref int offset, ref int count)
        {
            return _context!.Decrypt(buffer, ref offset, ref count);
        }

        //
        // This method assumes that a SSPI context is already in a good shape.
        // For example it is either a fresh context or already authenticated context that needs renegotiation.
        //
        private Task? ProcessAuthentication(bool isAsync = false, bool isApm = false, CancellationToken cancellationToken = default)
        {
            Task? result;

            ThrowIfExceptional();

            if (isAsync)
            {
                result = ForceAuthenticationAsync(new AsyncSslIOAdapter(this, cancellationToken), _context!.IsServer, null, isApm);
            }