all goroutines are asleep - deadlock!

2,081 views
Skip to first unread message

prank...@gmail.com

unread,
Aug 4, 2017, 11:18:52 AM8/4/17
to golang-nuts
Factorial Program in GoLang. Encountering deadlock.

Hello All,

I am pretty new to GoLang , so please excuse me if question/doubt is silly. 

I am trying to write a Factorial program of numbers ranging from 0 to 5. My goal is to launch separate GO routines for each number and then collect o/p and print it. I have tries writing code which can be seen @ https://play.golang.org/p/MTzTuroxE5 (also below) .. but i am encountering DEADLOCK error. I have been trying to synchronize it but i have failed to do it so far. Please help me in understanding that how else i can write this program so that i properly close sending channel to avoid error.

--
package main

import (
"fmt"
"sync"
)

var wg sync.WaitGroup

func factorial(x int) int {
if x > 0 {
return x*factorial(x-1)
}
return 1
}

func fact_worker(fact_resp_chan chan string, x int) {
defer wg.Done()
response := factorial(x)
fact_resp_chan <-  fmt.Sprintf("Factorial of %d is : %d", x, response)
}


func main() {
fact_chan := make(chan string)

for n := 0; n <=5 ; n++ {
wg.Add(1)
go fact_worker(fact_chan, n)
}



for resp := range(fact_chan) {
fmt.Printf("%s\n", resp)
}
wg.Wait()

}
--

Thanks!

Shawn Milochik

unread,
Aug 4, 2017, 11:43:18 AM8/4/17
to golang-nuts
Nothing ever closes the channel, so your last "for" loop blocks reading from it.

Jannick Fahlbusch

unread,
Aug 4, 2017, 12:51:17 PM8/4/17
to golan...@googlegroups.com
Hi,

you need to spin up another goroutine which ranges over the channel:
https://play.golang.org/p/OhLd6vOBYE

The reason for the deadlock is: You spin up N workers which are sending
the results over the "fact_chan"-Channel. After you did this, you are
listening on the main-routine for messages on fact_chan forever. But
after all of the workers finished their tasks, there is nobody to send
data. The runtime detects this and panics.

- Jannick

Am 04.08.2017 um 17:11 schrieb prank...@gmail.com:
> *Factorial Program in GoLang. Encountering deadlock.*
> *
> *
> *Hello All,*
> *
> *
> --
> You received this message because you are subscribed to the Google
> Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to golang-nuts...@googlegroups.com
> <mailto:golang-nuts...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.

Shawn Milochik

unread,
Aug 4, 2017, 12:55:54 PM8/4/17
to golang-nuts
On Fri, Aug 4, 2017 at 11:45 AM, Jannick Fahlbusch <jan...@jf-projects.de> wrote:
Hi,

you need to spin up another goroutine which ranges over the channel:
https://play.golang.org/p/OhLd6vOBYE



This has a race condition. There's no guarantee that all the lines will be printed before main() exits. A better solution is to close the channel so the range loop exits. I posted an example of that an hour ago: https://play.golang.org/p/mKdzU1z6Tx

Konstantin Khomoutov

unread,
Aug 7, 2017, 2:57:23 AM8/7/17
to golang-nuts
On Fri, Aug 04, 2017 at 08:11:45AM -0700, prank...@gmail.com wrote:

[...]
> func fact_worker(fact_resp_chan chan string, x int) {
> defer wg.Done()
> response := factorial(x)
> fact_resp_chan <- fmt.Sprintf("Factorial of %d is : %d", x, response)
> }
[...]

Please also consider naming your identifiers consistently with what the
Go itself and the community uses — for instance, [1, 2].

That is, use factWorker and factRespChan.

"Snake case" (foo_bar) is not used in Go code.

1. https://golang.org/doc/effective_go.html#names
2. https://blog.golang.org/package-names

Tong Sun

unread,
Mar 25, 2022, 10:27:02 AM3/25/22
to golang-nuts
Re-using the old thread for a new problem that I'm getting:

fatal error: all goroutines are asleep - deadlock!

I rewrote my https://github.com/suntong/lang/blob/master/lang/Go/src/sys/butchers.go files from procedure based to OO based, as

The two programs behaves exactly the same, however my new "OO" approach ended with 

fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:

The only reason that I can think of is that,

I changed my goroutine calling from function calling of
`go choppingProblem(i, knifeLeft, knifeRight)`

to method calling of
`go chopping.choppingAction(i, knifeLeft, knifeRight, &st)`

Might that be the reason? 
How to fix the problem?

Thanks


jake...@gmail.com

unread,
Mar 25, 2022, 12:08:39 PM3/25/22
to golang-nuts
The WaitGroup Documentation says " A WaitGroup must not be copied after first use.".

You are passing around and calling choppingActivity by value, so it is being copied after Add() is called, and again each call to choppingAction() and choppingSimulation().

If you run "go vet" on your code it will alert you to the problems.

Tong Sun

unread,
Mar 25, 2022, 1:14:56 PM3/25/22
to golang-nuts
Oh, thanks for the explain and pointing out `go vet` for future problems. 

Thanks!
Reply all
Reply to author
Forward
0 new messages