Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package modbus
import (
"encoding/binary"
"fmt"
"time"
)

// logger is the interface to the required logging functions
Expand Down Expand Up @@ -487,12 +488,25 @@ func (mb *client) send(request *ProtocolDataUnit) (response *ProtocolDataUnit, e
if err != nil {
return
}
aduResponse, err := mb.transporter.Send(aduRequest)
if err != nil {
return
}
if err = mb.packager.Verify(aduRequest, aduResponse); err != nil {
return

// Wait for correct response ID before throwing error.
var aduResponse []byte
maxTime := time.Now().Add(tcpTimeout)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tcpTimeout is a constant defined in tcpclient.go and is meaningless here.
client.go's send method is shared by all transports (TCP, RTU, ASCII). For an RTU serial client the timeout is serialTimeout. There is no single correct timeout constant to use here; this approach needs to be rethought.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point. Unfortunately it is unlikely I'll have the time for this in the near future.

for {
aduResponse, err = mb.transporter.Send(aduRequest)
if err != nil {
return
}
err = mb.packager.Verify(aduRequest, aduResponse)

if err == nil {
break
}
if time.Now().After(maxTime) {
err = fmt.Errorf("modbus: response timeout")
return
}
Comment on lines +649 to +652
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loop never checks ctx.Done(), so it will ignore context cancellation/deadline and continue running past the context timeout - i guess it was'nt there when you issued the PR. The custom fmt.Errorf("modbus: response timeout") also hides the actual error from Verify, which callers could find useful. The ctx deadline should be the upper bound.

// Else try again until timeout.
}
response, err = mb.packager.Decode(aduResponse)
if err != nil {
Expand Down