internalClose is called if there is an unexpected error during normal operation.
(err error)
| 963 | |
| 964 | // internalClose is called if there is an unexpected error during normal operation. |
| 965 | func (c *rawConnection) internalClose(err error) { |
| 966 | c.closeOnce.Do(func() { |
| 967 | c.startStopMut.Lock() |
| 968 | |
| 969 | l.Debugf("close connection to %s at %s due to %v", c.deviceID.Short(), c.ConnectionInfo, err) |
| 970 | if cerr := c.closer.Close(); cerr != nil { |
| 971 | l.Debugf("failed to close underlying conn %s at %s %v:", c.deviceID.Short(), c.ConnectionInfo, cerr) |
| 972 | } |
| 973 | close(c.closed) |
| 974 | |
| 975 | c.awaitingMut.Lock() |
| 976 | for i, ch := range c.awaiting { |
| 977 | if ch != nil { |
| 978 | close(ch) |
| 979 | delete(c.awaiting, i) |
| 980 | } |
| 981 | } |
| 982 | c.awaitingMut.Unlock() |
| 983 | |
| 984 | if !c.startTime.IsZero() { |
| 985 | // Wait for the dispatcher loop to exit, if it was started to |
| 986 | // begin with. |
| 987 | <-c.dispatcherLoopStopped |
| 988 | } |
| 989 | |
| 990 | c.startStopMut.Unlock() |
| 991 | |
| 992 | // We don't want to call into the model while holding the |
| 993 | // startStopMut. |
| 994 | c.model.Closed(err) |
| 995 | }) |
| 996 | } |
| 997 | |
| 998 | // The pingSender makes sure that we've sent a message within the last |
| 999 | // PingSendInterval. If we already have something sent in the last |