[#307] rpc: proper handling of context cancellation for transportmux + dataconn

- prior to this patch, context cancellation would leave rpc.Server open
- did not make problems because context was only cancelled by SIGINT,
  which was immediately followed by os.Exit
This commit is contained in:
Christian Schwarz
2020-04-20 21:24:42 +02:00
parent f772b3d39f
commit bcb5965617
5 changed files with 107 additions and 26 deletions
@@ -33,8 +33,12 @@ import (
type Logger = logger.Logger
type acceptRes struct {
conn *transport.AuthConn
err error
}
type acceptReq struct {
callback chan net.Conn
callback chan acceptRes
}
type Listener struct {
@@ -64,10 +68,19 @@ func New(authListener transport.AuthenticatedListener, l Logger) *Listener {
// The returned net.Conn is guaranteed to be *transport.AuthConn, i.e., the type of connection
// returned by the wrapped transport.AuthenticatedListener.
func (a Listener) Accept() (net.Conn, error) {
req := acceptReq{make(chan net.Conn, 1)}
a.accepts <- req
conn := <-req.callback
return conn, nil
req := acceptReq{make(chan acceptRes, 1)}
select {
case a.accepts <- req:
case <-a.stop:
return nil, fmt.Errorf("already closed") // TODO net.Error
}
res, ok := <-req.callback
if !ok {
return nil, fmt.Errorf("already closed") // TODO net.Error
}
return res.conn, res.err
}
func (a Listener) handleAccept() {
@@ -77,18 +90,9 @@ func (a Listener) handleAccept() {
a.logger.Debug("handleAccept stop accepting")
return
case req := <-a.accepts:
for {
a.logger.Debug("accept authListener")
authConn, err := a.al.Accept(context.Background())
if err != nil {
a.logger.WithError(err).Error("accept error")
continue
}
a.logger.WithField("type", fmt.Sprintf("%T", authConn)).
Debug("accept complete")
req.callback <- authConn
break
}
a.logger.Debug("accept authListener")
authConn, err := a.al.Accept(context.Background())
req.callback <- acceptRes{authConn, err}
}
}
}