Runtime: goroutine blocks forever

Hello all,
I have this bit of Golang code here

When I run this, it blocks forever and my assumption is due to the behavior of time.Tick which possibly results in a leak and the range over a channel which blocks as long as there’s a possibility of a write into the channel.

I would like to get help on clarity as to whether or not my understanding of this situation is correct.

I think your last for loop is waiting for the channel to close. And your goroutine is blocking waiting for new data on the channel that never arrives.

Thank you for your response @mje
On the part of the blocking goroutine. I understand that the routine can be blocked within its own self but is this supposed to affect the main routine?

Both the main goroutine and your child goroutine are blocked waiting on reading channels that never have more data but are not closed. The child goroutine does not cause the main goroutine to block. If you want either of the goroutines to continue, you need to close their channel. The playground times out because the main goroutine is waiting for more data.

@mje That’s correct in regards to ranging over a channel but the range over the channel is expected to deadlock at a point when the runtime can no longer detect the possibility of a future write into the channel.

Say for example, this code here. It’s basically the code from above but without the go routine. Running it will deadlock as expected which makes we wonder why the other part, once added, causes the code to block forever since the main routine and goroutine are independent.

All I can guess is that the go runtime must treat blocking writing to the channel burstyLimiter <- t differently from ranging over the channel in the main goroutine with regards to deadlock detection.

@mje So, here’s my possible justification… just hoping it’s the right one.

a range over a channel will listen to incoming messages to that channel and will never stop until the runtime figures that there’s no possibility of writing into the channel in the future.
now…this means that if you have a single routine and there’s no case where the routine will write into the channel, the range will stop and run into a deadlock if the channel never received a close signal.
now, because there’s a goroutine somewhere inside the main routine, the runtime has to wait because it is unsure whether or not there will be a write into the range channel.

But why is the runtime unsure? Well…this is likely because the goroutine inside the main routine is ranging over a time.Tick which is known to be prone to resource/memory leak.

now, the other go routine that has the time.Tick is writing into a channel that’s full…that will cause a block and the routine will stay open for ever.
Now, since the main routine thinks the subroutine is still working and might be in need of the burstyRequest channel range (it’s a matter of tendency), it will never run the range into a deadlock hence, the waiting forever.

I don’t know if this probably is right or wrong :smiling_face_with_tear:

I think you’re right that this might happen because the other goroutine is still running: I rewrote your second example with an infinite for loop and it doesn’t deadlock anymore: Go Playground - The Go Programming Language

Here is a similar stackoverflow post: go - Detect deadlock between a group of goroutines - Stack Overflow

EDIT: apparently, the Go deadlock detector issues a deadlock if the number of threads created and active is higher than the number of threads waiting for work (overly simplified). This means that a “spinning” goroutine such as this one will trick the deadlock detector. I’ve found this explained in this medium post and in a stack overflow post (which I can’t link yet because I can give a max of 2 links:') )

1 Like

That’s right @ozoniuss I really appreciate this articles you linked. I do hope you’ll be able to link the last one once the forum allows you the access. Really appreciate everyone’s contribution in providing clarity to the question.

Here’s the last post I was talking about (although it looks to me that the line of code linked is outdated): Understanding Go channel deadlocks - Stack Overflow

Thank you again @ozoniuss

Thank you @mje

1 Like

Thanks for this Guide
I have done all this work on an parallel app like capcut mod apk but it has some errors as you can see.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.