gopcua / opcua

Native Go OPC-UA library
MIT License
856 stars 259 forks source link

Panic in secure_channel.go #640

Closed aschiffmann closed 1 year ago

aschiffmann commented 1 year ago

Hello, I got a panic when calling ReadWithContext(). I cannot reproduce the error, I was calling the function a huge number of times before and without any change in the setup I randomly got this panic once.

Do you have an idea what could be the reason for it and how to prevent it?

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

goroutine 63 [running]: github.com/gopcua/opcua/uasc.(SecureChannel).SendRequestWithTimeoutWithContext(0x0, {0xc63d20, 0xc00003c058}, {0xc618d8, 0xc000410360}, 0xa053c0?, 0xc0004dda80?, 0x10bd360?) github.com/gopcua/opcua@v0.3.11/uasc/secure_channel.go:748 +0x4f github.com/gopcua/opcua.(Client).sendWithTimeout(0x108c8a0?, {0xc63d20?, 0xc00003c058?}, {0xc618d8?, 0xc000410360?}, 0xc0004ddaf0?, 0x40f9a7?) github.com/gopcua/opcua@v0.3.11/client.go:942 +0x136 github.com/gopcua/opcua.(Client).SendWithContext(0xc00058c690, {0xc63d20, 0xc00003c058}, {0xc618d8, 0xc000410360}, 0xa9a420?) github.com/gopcua/opcua@v0.3.11/client.go:925 +0x91 github.com/gopcua/opcua.(Client).ReadWithContext(0xa320c0?, {0xc63d20, 0xc00003c058}, 0xc0003e3b00) github.com/gopcua/opcua@v0.3.11/client.go:1014 +0x29c

magiconair commented 1 year ago

I think this is caused by this line which re-creates the secure channel and sets the internal secure channel instance temporarily to nil.

https://github.com/gopcua/opcua/blob/v0.3.11/client.go#L355

We don't catch this properly so this line fails with a nil pointer error since c.SecureChannel() returns nil until the channel has been restored.

https://github.com/gopcua/opcua/blob/v0.3.11/client.go#L942

Need to think about this a bit. What response should we return?

magiconair commented 1 year ago

Looking at the code I am finding some race conditions like this one. The initial nil check does not trigger but when we make the actual send request it fails since the connection is re-established.

image