Skip to content

Commit

Permalink
bug: fix the potential UDP socket leaks for Windows client
Browse files Browse the repository at this point in the history
  • Loading branch information
panjf2000 committed Jul 3, 2024
1 parent 26e13bb commit 3f9e09b
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 47 deletions.
2 changes: 1 addition & 1 deletion client_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func (cli *Client) EnrollContext(nc net.Conn, ctx interface{}) (gc Conn, err err
c := newUDPConn(cli.el, nil, nc.LocalAddr(), nc.RemoteAddr())
c.SetContext(ctx)
c.rawConn = nc
cli.el.ch <- &openConn{c: c, isDatagram: true, cb: func() { close(connOpened) }}
cli.el.ch <- &openConn{c: c, cb: func() { close(connOpened) }}
go func(uc net.Conn, el *eventloop) {
var buffer [0x10000]byte
for {
Expand Down
1 change: 0 additions & 1 deletion connection_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ type udpConn struct {
type openConn struct {
c *conn
cb func()
isDatagram bool
}

type conn struct {
Expand Down
29 changes: 2 additions & 27 deletions eventloop_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"errors"
"fmt"
"io"
"net"
"os"
"strings"
"time"
Expand Down Expand Up @@ -232,33 +231,8 @@ func (el *eventloop) close(c *conn, err error) error {
return nil // ignore stale connections
}

action := el.eventHandler.OnClose(c, err)

var errStr strings.Builder

if _, ok := c.localAddr.(*net.UDPAddr); ok {
if err := el.poller.Delete(c.fd); err != nil {
err = fmt.Errorf("failed to delete fd=%d from poller in event-loop(%d): %v",
c.fd, el.idx, os.NewSyscallError("delete", err))
errStr.WriteString(err.Error())
errStr.WriteString(" | ")
}
if _, ok := el.listeners[c.fd]; !ok {
if err := unix.Close(c.fd); err != nil {
err = fmt.Errorf("failed to close fd=%d in event-loop(%d): %v",
c.fd, el.idx, os.NewSyscallError("close", err))
errStr.WriteString(err.Error())
}
el.connections.delConn(c)
}
c.release()
if errStr.Len() > 0 {
return errors.New(strings.TrimSuffix(errStr.String(), " | "))
}
return el.handleAction(c, action)
}

el.connections.delConn(c)
action := el.eventHandler.OnClose(c, err)

// Send residual data in buffer back to the remote before actually closing the connection.
for !c.outboundBuffer.IsEmpty() {
Expand All @@ -275,6 +249,7 @@ func (el *eventloop) close(c *conn, err error) error {

c.release()

var errStr strings.Builder
err0, err1 := el.poller.Delete(c.fd), unix.Close(c.fd)
if err0 != nil {
err0 = fmt.Errorf("failed to delete fd=%d from poller in event-loop(%d): %v",
Expand Down
24 changes: 6 additions & 18 deletions eventloop_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"bytes"
"context"
"errors"
"net"
"runtime"
"sync/atomic"
"time"
Expand Down Expand Up @@ -97,10 +96,8 @@ func (el *eventloop) open(oc *openConn) error {
}

c := oc.c
if !oc.isDatagram {
el.connections[c] = struct{}{}
el.incConn(1)
}
el.connections[c] = struct{}{}
el.incConn(1)

out, action := el.eventHandler.OnOpen(c)
if out != nil {
Expand Down Expand Up @@ -192,23 +189,14 @@ func (el *eventloop) close(c *conn, err error) error {
return nil // ignore stale wakes.
}

delete(el.connections, c)
el.incConn(-1)
action := el.eventHandler.OnClose(c, err)
err = nil

if _, ok := c.localAddr.(*net.UDPAddr); ok {
if c.rawConn != nil {
err = c.rawConn.Close()
}
c.release()
if err != nil {
return err
}
return el.handleAction(c, action)
if c.rawConn != nil {
err = c.rawConn.Close()
}

delete(el.connections, c)
el.incConn(-1)
err = c.rawConn.Close()
c.release()
if err != nil {
return err

Check warning on line 202 in eventloop_windows.go

View check run for this annotation

Codecov / codecov/patch

eventloop_windows.go#L202

Added line #L202 was not covered by tests
Expand Down

0 comments on commit 3f9e09b

Please sign in to comment.