lorenzodonini/ocpp-go

Infinite wait on stopping a disconnected charge point

adippel opened this issue · 1 comments

Just discovered that calling

func (cp *chargePoint) Stop() {

leads to an infinite loop when the charge point is already disconnected from the central system. This is due to a bug in:

ocpp-go/ocppj/client.go

Lines 108 to 118 in e034d39

func (c *Client) Stop() {
// Overwrite handler to intercept disconnected signal
cleanupC := make(chan struct{}, 1)
c.client.SetDisconnectedHandler(func(err error) {
cleanupC <- struct{}{}
})
c.client.Stop()
c.dispatcher.Stop()
// Wait for websocket to be cleaned up
<-cleanupC
}

Waiting for a message on cleanupC that is expected to be sent when the underlying web socket connection is closed is just not feasible on an already closed web socket connection.

Registering the callback handler depending on the current connection state should do the trick. Simply closing the channel when we are already disconnected avoids the infinite loop.

This might be a starter for a patch:

func (c *Client) Stop() {
	// Overwrite handler to intercept disconnected signal
	cleanupC := make(chan struct{}, 1)
	if c.client.IsConnected() {
		c.client.SetDisconnectedHandler(func(err error) {
			cleanupC <- struct{}{}
		})
	} else {
		close(cleanupC)
	}

	c.client.Stop()
	c.dispatcher.Stop()
	// Wait for websocket to be cleaned up
	<-cleanupC
}

I am happy to provide a PR for this or discuss this issue further.

Thanks for finding this edge case. I have a branch open with a fix based on the suggested code. It actually needs one more tweak in the lower websocket layer to prevent follow-up errors. I'm working on that and will write a test case to verify this.