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

panic due to concurrent closeIdle and Send() #88

Open
dataselfservice opened this issue Nov 27, 2022 · 0 comments
Open

panic due to concurrent closeIdle and Send() #88

dataselfservice opened this issue Nov 27, 2022 · 0 comments

Comments

@dataselfservice
Copy link

Hi,

running version 606c02f and RTU 60 seconds sampling rate (modbus polls) == serialIdleTimeout, after changing hardware (to faster one) the following panic occured.

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0xb5ac4]
goroutine 21 [running]:
io.ReadAtLeast(0x0, 0x0, 0x1cc4a00, 0x100, 0x100, 0x4, 0x0, 0x399844, 0x1c1ad60)
        io/io.go:328 +0x40
github.com/goburrow/modbus.(*rtuSerialTransporter).Send(0x1c86804, 0x1c1ad60, 0x8, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0)
        github.com/goburrow/[email protected]/rtuclient.go:137 +0x1dc
github.com/goburrow/modbus.(*client).send(0x1c0e9e0, 0x1c0edc0, 0x2, 0x1c1ad5c, 0x4)
        github.com/goburrow/[email protected]/client.go:443 +0x80
github.com/goburrow/modbus.(*client).ReadHoldingRegisters(0x1c0e9e0, 0x50000, 0x39c8b8, 0x1c18c30, 0x0, 0x1, 0x456001)
        github.com/goburrow/[email protected]/client.go:112 +0xb4
...

It appears closeIdle, from modbus/serial.go:90 runs in parallel with Send, from modbus/rtuclient.go:113. In some (unfrequent cases) mb.close(), modbus/serial.go:100, from previous Send, occurs in currentSend after 124 and before 137, resulting in panic on line 137.

113 func (mb *rtuSerialTransporter) Send(aduRequest []byte) (aduResponse []byte, err error) {
114         // Make sure port is connected
115         if err = mb.serialPort.connect(); err != nil {
116                 return
117         }
118         // Start the timer to close when idle
119         mb.serialPort.lastActivity = time.Now()
120         mb.serialPort.startCloseTimer()
121         
122         // Send the request
123         mb.serialPort.logf("modbus: sending % x\n", aduRequest)
124         if _, err = mb.port.Write(aduRequest); err != nil {
125                 return
126         }
127         function := aduRequest[1]
128         functionFail := aduRequest[1] & 0x80
129         bytesToRead := calculateResponseLength(aduRequest)
130         time.Sleep(mb.calculateDelay(len(aduRequest) + bytesToRead))
131         
132         var n int
133         var n1 int
134         var data [rtuMaxSize]byte
135         //We first read the minimum length and then read either the full package
136         //or the error package, depending on the error status (byte 2 of the response)
137         n, err = io.ReadAtLeast(mb.port, data[:], rtuMinSize)
138         if err != nil {
139                 return
140         }
...
dataselfservice pushed a commit to dataselfservice/modbus that referenced this issue Nov 27, 2022
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

1 participant