12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- // Copyright 2009 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:build linux && go1.25 && badlinkname
- package ktls
- import (
- "fmt"
- "net"
- "time"
- )
- func (c *Conn) Close() error {
- if !c.kernelTx {
- return c.Conn.Close()
- }
- // Interlock with Conn.Write above.
- var x int32
- for {
- x = c.rawConn.ActiveCall.Load()
- if x&1 != 0 {
- return net.ErrClosed
- }
- if c.rawConn.ActiveCall.CompareAndSwap(x, x|1) {
- break
- }
- }
- if x != 0 {
- // io.Writer and io.Closer should not be used concurrently.
- // If Close is called while a Write is currently in-flight,
- // interpret that as a sign that this Close is really just
- // being used to break the Write and/or clean up resources and
- // avoid sending the alertCloseNotify, which may block
- // waiting on handshakeMutex or the c.out mutex.
- return c.conn.Close()
- }
- var alertErr error
- if c.rawConn.IsHandshakeComplete.Load() {
- if err := c.closeNotify(); err != nil {
- alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err)
- }
- }
- if err := c.conn.Close(); err != nil {
- return err
- }
- return alertErr
- }
- func (c *Conn) closeNotify() error {
- c.rawConn.Out.Lock()
- defer c.rawConn.Out.Unlock()
- if !*c.rawConn.CloseNotifySent {
- // Set a Write Deadline to prevent possibly blocking forever.
- c.SetWriteDeadline(time.Now().Add(time.Second * 5))
- *c.rawConn.CloseNotifyErr = c.sendAlertLocked(alertCloseNotify)
- *c.rawConn.CloseNotifySent = true
- // Any subsequent writes will fail.
- c.SetWriteDeadline(time.Now())
- }
- return *c.rawConn.CloseNotifyErr
- }
|