Repository: syncthing/syncthing (language: go)

Issue:
relaysrv crash after some weeks of operation
strelaysrv v1.22.1 "Fermium Flea" (go1.19.2 linux-amd64) deb@build.syncthing.net 2022-11-02 06:27:53 UTC [noupgrade]

After some weeks of operation syncthing relayserver crashes with (from the debug log):
```
syncthing-relaysrv: panic: runtime error: invalid memory address or nil pointer dereference
syncthing-relaysrv: [signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x9cd307]
syncthing-relaysrv: 
syncthing-relaysrv: goroutine 14 [running]:
syncthing-relaysrv: main.listener({0x0?, 0x0?}, {0xaf26dc?, 0x0?}, 0xc00026e000, {0x0, 0x0})
syncthing-relaysrv: #011github.com/syncthing/syncthing/cmd/strelaysrv/listener.go:40 +0xc7
syncthing-relaysrv: created by main.main
syncthing-relaysrv: #011github.com/syncthing/syncthing/cmd/strelaysrv/main.go:280 +0x2213
```
No unusual action is logged before the crash.
There is no hint in the syslog.
There were around 7000 session handled on the day of the crash. 
The crash happened already several times. I've never experienced such a crash with versions before 1.22.1.



Discussion / hints:
Not really obvious what happened. Perhaps something in the kernel killed the connection? The machine wasn't low on ram etc?

Is that all there is in the crash log?
Normally strelaysrv consumes <1% of the RAM and there are over 15GB free. If the kernel killed the connection, I think there would be soemthing in syslog, but there is nothing.

I just saw, I ran it with "-network-buffer 3072". Is it possible that the server crashes, when the proxied connections  exhaust the network-buffer?

If the crash log isn't different from the normal log, no.
This looks like something randomly become nil, so its not clear why that happened 
Nah this is a simple bug, present since Forever&trade; apparently.

https://github.com/syncthing/syncthing/blob/dc5e10fa2c59ae21376aab94a6019e807718b781/cmd/strelaysrv/listener.go#L38-L43

`conn` can easily be nil here if the accept call failed for whatever reason, so then we shouldn't try to log the address of the connection we didn't get.

(we return a conn plus an error if the TLS handshake fails, but we can fail already in the accept and then it's a `return nil, false, err`)

Fix patch:
diff --git a/cmd/strelaysrv/listener.go b/cmd/strelaysrv/listener.go
index dc3724c0f82..c89f8a2c802 100644
--- a/cmd/strelaysrv/listener.go
+++ b/cmd/strelaysrv/listener.go
@@ -36,8 +36,14 @@ func listener(_, addr string, config *tls.Config, token string) {
 	for {
 		conn, isTLS, err := listener.AcceptNoWrapTLS()
 		if err != nil {
+			// Conn may be nil if accept failed, or non-nil if the initial
+			// read to figure out if it's TLS or not failed. In the latter
+			// case, close the connection before moving on.
+			if conn != nil {
+				conn.Close()
+			}
 			if debug {
-				log.Println("Listener failed to accept connection from", conn.RemoteAddr(), ". Possibly a TCP Ping.")
+				log.Println("Listener failed to accept:", err)
 			}
 			continue
 		}


Test patch: