go: net: ReadFromUDP hangs (randomly) even when ReadDeadline is crossed

What version of Go are you using (go version)?

$ go version
> go1.13.4 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

Ubuntu 18.04.2 LTS | Kernel version: 4.15.0-66-generic

What did you do?

This function is called as a gorutine:

// Listens infinitely for UDP packet arrivals and
// executes it's processing inside a gorutine.
func startUDPListener(netw string, router *Router) {
	lAddr := getLocalIPAddress()
	// Set listening port.
	lAddr.Port = int(router.myPeerInfo.port)
	PacketConnCreation:
	// listen to incoming udp packets
	pc, err := net.ListenUDP(netw, &lAddr)
	if err != nil {
		log.Panic(err)
	}
	// Set initial deadline.
	pc.SetReadDeadline(time.Now().Add(time.Minute))

	for {
		//simple read
		buffer := make([]byte, 1024)

		byteNum, uAddr, err := pc.ReadFromUDP(buffer)

		if err != nil {
                        // If we get an error, we just close the pc and create a new one.
			log.Printf("%v", err)
			pc.Close()
			goto PacketConnCreation
		} else {
			// Set a new deadline for the connection.
			pc.SetReadDeadline(time.Now().Add(5 * time.Minute))
			go processPacket(*uAddr, byteNum, buffer, router)
			
		}
	}
}

What did you expect to see?

I was expecting ReadFromUDP to ALWAYS return an error if the DeadLine is crossed and I don’t recieve any UDP packet on my IP:Port interface before this happens.

What did you see instead?

Instead of that, it sometimes hangs completely without giving any kind of errors. It’s completely random, it sometimes hangs and sometimes doesn’t (providing the corresponding i/o timeout)

It just stays running forever without accepting new packets (or even reading them). The gorutine gets completely freezed (or at least it seems so).

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 23 (4 by maintainers)

Most upvoted comments

For the record, never write for {} in a Go program. That will never work well. See #10958 for part of the problem.

Please try precisely what I suggested. Don’t invent a new concept. If you want the main goroutine to go to sleep forever then select {} is the construct you should use.

Can you please try rewriting your code to use select {} rather than for {}

On 3 Dec 2019, at 12:50, Carlos Pérez notifications@github.com wrote:

Same as this (i removed the docker part of it since I’m not using it at all)

2319K 1896M ACCEPT all – * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 185 9859 ACCEPT all – lo * 0.0.0.0/0 0.0.0.0/0
495 78143 DROP all – * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID 0 0 ACCEPT icmp – * * 0.0.0.0/0 0.0.0.0/0 icmptype 8 ctstate NEW 309 65818 UDP udp – * * 0.0.0.0/0 0.0.0.0/0 ctstate NEW 6638 269K TCP tcp – * * 0.0.0.0/0 0.0.0.0/0 tcp flags:0x17/0x02 ctstate NEW 288 64616 REJECT udp – * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable 6622 284K REJECT tcp – * * 0.0.0.0/0 0.0.0.0/0 reject-with tcp-reset 792 26940 REJECT all – * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-proto-unreachable 0 0 ACCEPT udp – * * 0.0.0.0/0 0.0.0.0/0 udp dpt:25519

Chain FORWARD (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination
0 0 ACCEPT all – * * 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT 653K packets, 61M bytes) pkts bytes target prot opt in out source destination
833K 293M ACCEPT udp – * * 0.0.0.0/0 0.0.0.0/0

Chain TCP (1 references) pkts bytes target prot opt in out source destination
33 1588 ACCEPT tcp – * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 51 2160 ACCEPT tcp – * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 13 528 ACCEPT tcp – * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443

Chain UDP (1 references) pkts bytes target prot opt in out source destination
2 148 ACCEPT udp – * * 0.0.0.0/0 0.0.0.0/0 udp dpt:5353 4 288 ACCEPT udp – * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53 15 766 ACCEPT udp – * * 0.0.0.0/0 0.0.0.0/0 udp dpt:25519 — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.