Skip to content

Commit a0f7d69

Browse files
authored
Merge pull request #6181 from mysteriumnetwork/fix-panic-connection
Improve state channel handling to prevent panics on closed channel
2 parents 6bb340f + 306bed8 commit a0f7d69

1 file changed

Lines changed: 19 additions & 5 deletions

File tree

‎services/wireguard/connection/connection.go‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ func (c *Connection) State() <-chan connectionstate.State {
8686
return c.stateCh
8787
}
8888

89+
// sendState safely sends a state to the state channel, preventing panics from sends on closed channel.
90+
func (c *Connection) sendState(state connectionstate.State) {
91+
select {
92+
case c.stateCh <- state:
93+
case <-c.done:
94+
// Connection is stopped, don't send
95+
}
96+
}
97+
8998
// Statistics returns connection statistics channel.
9099
func (c *Connection) Statistics() (connectionstate.Statistics, error) {
91100
stats, err := c.connectionEndpoint.PeerStats()
@@ -128,7 +137,7 @@ func (c *Connection) start(ctx context.Context, start startConn, options connect
128137
}
129138
}()
130139

131-
c.stateCh <- connectionstate.Connecting
140+
c.sendState(connectionstate.Connecting)
132141

133142
if options.ProviderNATConn != nil {
134143
options.ProviderNATConn.Close()
@@ -170,7 +179,7 @@ func (c *Connection) start(ctx context.Context, start startConn, options connect
170179
return errors.Wrap(err, "failed while waiting for a peer handshake")
171180
}
172181

173-
c.stateCh <- connectionstate.Connected
182+
c.sendState(connectionstate.Connected)
174183
return nil
175184
}
176185

@@ -224,7 +233,7 @@ func (c *Connection) GetConfig() (connection.ConsumerConfig, error) {
224233
func (c *Connection) Stop() {
225234
c.stopOnce.Do(func() {
226235
log.Info().Msg("Stopping WireGuard connection")
227-
c.stateCh <- connectionstate.Disconnecting
236+
c.sendState(connectionstate.Disconnecting)
228237

229238
if c.removeAllowedIPRule != nil {
230239
c.removeAllowedIPRule()
@@ -236,9 +245,14 @@ func (c *Connection) Stop() {
236245
}
237246
}
238247

239-
c.stateCh <- connectionstate.NotConnected
248+
// Send final state before closing channels
249+
select {
250+
case c.stateCh <- connectionstate.NotConnected:
251+
default:
252+
}
240253

241-
close(c.stateCh)
254+
// Close done first so sendState calls will bail out instead of sending on closed stateCh
242255
close(c.done)
256+
close(c.stateCh)
243257
})
244258
}

0 commit comments

Comments
 (0)