-2

Trying to familiarize myself with subroutines and Go overall, and I'm trying to write a script that will basically start up all the services of my django app with sync.WaitGroup and keep them running until i manually kill the Go script, which is why i'm not having the intitialize() function actually tell the waitgroup that the processes are finished. Getting the dreaded fatal error: all goroutines are asleep - deadlock! message.

 func main() {
    var wg sync.WaitGroup
    os.Chdir("/home/Projects/djangoapp")
    cc := []cmds{cmds{
        name:  "django",
        cmdsl: []string{"/home/Projects/djangoapp/env/bin/python", "manage.py", "runserver"},
    },
        cmds{
            name:  "celeryd",
            cmdsl: []string{"/home/Projects/djangoapp/env/bin/celery", "-A", "djangoapp", "worker", "-l", "INFO", "-S", "django"},
        },
    }

    for x := 0; x < 2; x++ {
        wg.Add(1)
        fmt.Println("starting up", cc[x].name)
        go initialize(cc[x])
    }
    wg.Wait()
}

func initialize(ccmds cmds) {
    cmd := exec.Command(ccmds.cmdsl[0], ccmds.cmdsl[1:]...)
    cmd.Env = append(os.Environ(), "DJANGO_SETTINGS_MODULE=articleadmin.settings.default")

    fmt.Println("initializing", ccmds.name)
    cmd.Start()
    fmt.Println("started", ccmds.name)
    cmd.Wait()
}

It starts up the services, but then barfs with the deadlock error. What am I doing wrong?

mcbrandt13
  • 46
  • 6
  • 1
    It might be because you're never calling `wg.Done`. You should pass the `WaitGroup` as a pointer (`&wg`) to your initialize function and then call `wg.Done()` after it finishes – xarantolus Feb 03 '20 at 17:30

1 Answers1

4

It looks like you forgot to call wg.Done when the goroutine is done:

 go initialize(&wg,cc[x])
...

func initialize(wg *sync.WaitGroup,ccmds cmds) {
  defer wg.Done()
  ...
}

Without that, wg.Wait will wait indefinitely. When all the goroutines terminate, main goroutine will be the only goroutine waiting on that WaitGroup, so deadlock.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • that's the thing. I want it to wait indefinitely until I just kill the script. the goroutines should just continue running indefinitely. – mcbrandt13 Feb 03 '20 at 17:43
  • If you got a deadlock error, your goroutines ended. You get a deadlock because wg.Wait is waiting and there are no other goroutines running. – Burak Serdar Feb 03 '20 at 17:53
  • "I want it to wait indefinitely until I just kill the script" then why use waitgroups at all? – Adrian Feb 03 '20 at 18:07
  • I don't need to use waitgroups, happy to use whatever method works best. – mcbrandt13 Feb 03 '20 at 19:02
  • Your problem is not the use of wait groups. You want your goroutines to never end, but they clearly do. – Burak Serdar Feb 03 '20 at 19:04
  • Yep, you're right. Something was off with my python env. Kids, check your commands to make sure they work before sticking them in exec.Command. Now to just pipe the outputs via a channel and i'll be all done. – mcbrandt13 Feb 03 '20 at 20:49