robinson / gos7

Implementation of Siemens S7 protocol in golang
BSD 3-Clause "New" or "Revised" License
315 stars 124 forks source link

how to detect a timed-out connection, and avoid panic on `client.AGReadDB` #46

Closed dataselfservice closed 3 years ago

dataselfservice commented 3 years ago

Hi,

trying to reuse a connection client when accessing the same Address, Rack, Slot to avoid multiple Connect():

        handler = gos7.NewTCPClientHandler(key.TcpDevice, key.Rack, key.Slot)
        handler.Timeout = 20 * time.Second
        handler.IdleTimeout = 20 * time.Second
        if debug {
                c.handler.Logger = log.New(os.Stdout, "tcp: ", log.Llongfile)
        }               
        err = handler.Connect()
        if err != nil { 
                log.Printf("connect err: %v", err)
                return
        }       

        client = gos7.NewClient(c.handler)

then:

err = client.AGReadDB(req.Address, req.WordStart, req.WordSize, buf)
...

if the connection drops (or goes into timeout): client.AGReadDB(req.Address, req.WordStart, req.WordSize, buf) panics with:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x3b5568]

goroutine 24 [running]:
github.com/robinson/gos7.(*tcpTransporter).Send(0x1c175c0, 0x1c1b300, 0x1f, 0x1f, 0x0, 0x0, 0x0, 0x0, 0x0)
        github.com/robinson/gos7@v0.0.0-20201216125248-2dd72fe148d3/tcpclient.go:117 +0x108
github.com/robinson/gos7.(*client).send(0x1c0d060, 0x1c62ce4, 0x1f, 0x1c1b300, 0x1dd70)
        github.com/robinson/gos7@v0.0.0-20201216125248-2dd72fe148d3/client.go:469 +0x44
github.com/robinson/gos7.(*client).readArea(0x1c0d060, 0x84, 0x5a, 0xc, 0x4, 0x2, 0x1c19124, 0x4, 0x4, 0x1, ...)
        github.com/robinson/gos7@v0.0.0-20201216125248-2dd72fe148d3/client.go:228 +0x2d0
github.com/robinson/gos7.(*client).AGReadDB(0x1c0d060, 0x5a, 0xc, 0x4, 0x1c19124, 0x4, 0x4, 0x0, 0x4)
        github.com/robinson/gos7@v0.0.0-20201216125248-2dd72fe148d3/client.go:76 +0x5c
...

Why is that panic-ing and how can I avoid that? E.g. detecting connection is dopped or invalid? Or reconnecting?

Cheers, DataSeflService

dataselfservice commented 3 years ago

Not sure this is best, but it at lease detects nil connection.

You might consider pulling this one: https://github.com/dataselfservice/gos7/commit/2aa923f348b06ae2fe634df493605cdcb7641b2e as a fix.