Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disconnect method triggers OnClientError callback with net.ErrClosed error #254

Open
robert197 opened this issue Apr 24, 2024 · 3 comments

Comments

@robert197
Copy link

When the Disconnect method is invoked with a specific reason code, the OnClientError callback is unexpectedly triggered with a net.ErrClosed error, even though the Disconnect operation itself returns nil. This suggests that the disconnection is being incorrectly treated as an error, potentially indicating an issue with how the library handles socket closures on client-initiated disconnects.

To reproduce

Configure the client with callbacks for server disconnections and client errors:

c := paho.NewClient(paho.ClientConfig{
    Router: router,
    Conn:   conn,
    OnServerDisconnect: func(d *paho.Disconnect) {
        fmt.Println("Server has been disconnected...")
    },
    OnClientError: func(err error) {
        fmt.Printf("Error: %s\n", err.Error())
    },
})

Disconnect the client using the Disconnect method with an administrative action reason code:

err := c.Disconnect(&paho.Disconnect{
    ReasonCode: byte(152), // Administrative Action
})

Expected behaviour:

The expected behavior is for the client to disconnect without invoking the OnClientError callback, as the disconnection is user-initiated and should not be treated as an error condition.

Software used:

MQTT Broker version: emqx:5.3.2
Client version: github.com/eclipse/paho.golang v0.10.1-0.20220826012857-d63b3b28d25f

Additional context

Currently, I am using a workaround that checks for net.ErrClosed in the OnClientError callback to differentiate between genuine errors and this disconnection handling issue. Here is the temporary code adjustment:

OnClientError: func(err error) {
    if errors.Is(err, net.ErrClosed) {
        fmt.Println("[MQTT] disconnection has been received")
    } else {
        panic(fmt.Sprintf("[MQTT] killing service because of unknown client error: %s", err.Error()))
    }
}

It seems there might be an issue with how the socket closure is managed during the disconnection process, perhaps attempting to close an already closed connection.

@MattBrittan
Copy link
Contributor

Client version: github.com/eclipse/paho.golang v0.10.1-0.20220826012857-d63b3b28d25f

That version is two years old; please try with master (or, at a minimum, v0.21). I know I've made a range of changes to the error handling in the interim.

@robert197
Copy link
Author

@MattBrittan Thanks for the info, I have updated the version to v0.21 but the behavior is still the same.

@MattBrittan
Copy link
Contributor

MattBrittan commented Apr 24, 2024

Thanks. The changes I was thinking of were in autopaho - see the errorHandler, this ensures only a single error is passed through (paho sometimes raises multiple errors when the connection is lost).

paho is intended to be a fairly low level library, and commonly returns multiple errors (as handled in by the above autopaho code). I'm not really sure whether to class this as a bug, as I believe that the way this works was deliberate (the error handling in paho.mqtt.golang led to quite a few deadlocks over the years, I'd guess this was a reaction to that). The documentation should definitely mention this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants