Repository: dotnet/runtime
File: src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs (C#)

Code before:
                    }

                    toRead = Math.Min(toRead, context._inputBuffer.ActiveLength);

                    context._inputBuffer.ActiveSpan.Slice(0, toRead).CopyTo(new Span<byte>(data, toRead));
                    context._inputBuffer.Discard(toRead);

                    *dataLength = toRead;
                    return PAL_SSLStreamStatus.OK;
                }
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                throw;
            }
        }

        [UnmanagedCallersOnly]
        private static void CleanupManagedContext(IntPtr managedContextHandle)
        {
            if (managedContextHandle != IntPtr.Zero)
            {
                GCHandle handle = GCHandle.FromIntPtr(managedContextHandle);
                if (handle.IsAllocated)
                {
                    handle.Free();
                }
            }
        }

        internal void Write(ReadOnlySpan<byte> buf)
        {
            lock (_lock)
            {
                _inputBuffer.EnsureAvailableSpace(buf.Length);
                buf.CopyTo(_inputBuffer.AvailableSpan);
                _inputBuffer.Commit(buf.Length);
            }
        }

        internal int BytesReadyForConnection => _outputBuffer.ActiveLength;

        internal void ReadPendingWrites(ref ProtocolToken token)
        {
            lock (_lock)
            {
                if (_outputBuffer.ActiveLength == 0)
                {
                    token.Size = 0;
                    token.Payload = null;

Review comment (suggestion):
```suggestion
```
This is unnecessary. Non-null `managedContextHandle` is always going to turn into Allocated GCHandle (even if the handle was freed somewhere else already).

GCHandle is struct that is as dangerous as unsafe code. If you call Free on one copy of the struct, the other copies will still report IsAllocated==true even through the handle was freed.

Code after:
                *dataLength = toRead;
                return PAL_SSLStreamStatus.OK;
            }
        }

        [UnmanagedCallersOnly]
        private static void CleanupManagedContext(IntPtr managedContextHandle)
        {
            if (managedContextHandle != IntPtr.Zero)
            {
                WeakGCHandle<SafeDeleteSslContext> handle = WeakGCHandle<SafeDeleteSslContext>.FromIntPtr(managedContextHandle);
                handle.Dispose();
            }
        }

        internal void Write(ReadOnlySpan<byte> buf)
        {
            lock (_lock)
            {
                _inputBuffer.EnsureAvailableSpace(buf.Length);
                buf.CopyTo(_inputBuffer.AvailableSpan);
                _inputBuffer.Commit(buf.Length);
            }
        }

        internal int BytesReadyForConnection => _outputBuffer.ActiveLength;

        internal void ReadPendingWrites(ref ProtocolToken token)
        {
            lock (_lock)
            {
                if (_outputBuffer.ActiveLength == 0)
                {
                    token.Size = 0;
                    token.Payload = null;
                    return;
                }

                token.SetPayload(_outputBuffer.ActiveSpan);
                _outputBuffer.Discard(_outputBuffer.ActiveLength);
            }
        }

        internal int ReadPendingWrites(byte[] buf, int offset, int count)
        {
            Debug.Assert(buf != null);
            Debug.Assert(offset >= 0);
            Debug.Assert(count >= 0);
            Debug.Assert(count <= buf.Length - offset);

            lock (_lock)