Skip to content

Commit

Permalink
fix: close conn when server OnRequest panic (#238)
Browse files Browse the repository at this point in the history
  • Loading branch information
joway authored Jul 14, 2023
1 parent 4b1feb1 commit f290ea8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
14 changes: 14 additions & 0 deletions connection_onevent.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,18 @@ func (c *connection) onProcess(isProcessable func(c *connection) bool, process f
}
// add new task
var task = func() {
panicked := true
defer func() {
// cannot use recover() here, since we don't want to break the panic stack
if panicked {
c.unlock(processing)
if c.IsActive() {
c.Close()
} else {
c.closeCallback(false)
}
}
}()
START:
// `process` must be executed at least once if `isProcessable` in order to cover the `send & close by peer` case.
// Then the loop processing must ensure that the connection `IsActive`.
Expand All @@ -189,6 +201,7 @@ func (c *connection) onProcess(isProcessable func(c *connection) bool, process f
// Handling callback if connection has been closed.
if !c.IsActive() {
c.closeCallback(false)
panicked = false
return
}
c.unlock(processing)
Expand All @@ -197,6 +210,7 @@ func (c *connection) onProcess(isProcessable func(c *connection) bool, process f
goto START
}
// task exits
panicked = false
return
}

Expand Down
31 changes: 31 additions & 0 deletions netpoll_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,37 @@ func TestServerReadAndClose(t *testing.T) {
MustNil(t, err)
}

func TestServerPanicAndClose(t *testing.T) {
var network, address = "tcp", ":18888"
var sendMsg = []byte("hello")
var paniced int32
var loop = newTestEventLoop(network, address,
func(ctx context.Context, connection Connection) error {
_, err := connection.Reader().Next(len(sendMsg))
MustNil(t, err)
atomic.StoreInt32(&paniced, 1)
panic("test")
},
)

var conn, err = DialConnection(network, address, time.Second)
MustNil(t, err)
_, err = conn.Writer().WriteBinary(sendMsg)
MustNil(t, err)
err = conn.Writer().Flush()
MustNil(t, err)

for atomic.LoadInt32(&paniced) == 0 {
runtime.Gosched() // wait for poller close connection
}
for conn.IsActive() {
runtime.Gosched() // wait for poller close connection
}

err = loop.Shutdown(context.Background())
MustNil(t, err)
}

func TestClientWriteAndClose(t *testing.T) {
var (
network, address = "tcp", ":18889"
Expand Down

0 comments on commit f290ea8

Please sign in to comment.