in conn.go [336:381]
func (c *Conn) start(ctx context.Context) (err error) {
// only start connWriter and connReader if there was no error
// NOTE: this MUST be the first defer in this scope so that the
// defer for the interruptor goroutine executes first
defer func() {
if err == nil {
// we can't create the channel bitmap until the connection has been established.
// this is because our peer can tell us the max channels they support.
c.channels = bitmap.New(uint32(c.channelMax))
go c.connWriter()
go c.connReader()
}
}()
// if the context has a deadline or is cancellable, start the interruptor goroutine.
// this will close the underlying net.Conn in response to the context.
if ctx.Done() != nil {
done := make(chan struct{})
interruptRes := make(chan error, 1)
defer func() {
close(done)
if ctxErr := <-interruptRes; ctxErr != nil {
// return context error to caller
err = ctxErr
}
}()
go func() {
select {
case <-ctx.Done():
c.closeDuringStart()
interruptRes <- ctx.Err()
case <-done:
interruptRes <- nil
}
}()
}
if err = c.startImpl(ctx); err != nil {
return
}
return
}