GoLang program waiting instead of panicking with "all goroutines are asleep - deadlock" [duplicate]
Asked Answered
T

0

7

When I run Program 1 with command go run main.go it terminates with error all goroutines are asleep - deadlock! while the Program 2 keep waiting and does not terminate. We are not calling checkLink function and still we are seeing different behaviour. Can you please explain this?

Also when I ran the executable file which is output of go build main.go for Program 2, It was killed and executable file deleted.

Program 1

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)
    c <- 4
    x := <-c
    fmt.Println(x)
}

Program 2

package main

import (
    "fmt"
    "net/http"
)

func main() {
    c := make(chan int)
    c <- 4
    x := <-c
    fmt.Println(x)
}

func checkLink(link string, c chan string) {
    fmt.Println("checking", link)
    _, err := http.Get(link)
    if err != nil {
        c <- link + " is down"
        return
    }
    c <- link + " is up"
}

NOTE: I am running this on macOS and shell is ZSH

Edit The behaviour of Program 2 is the same as that of Program 1 when I run it in Go Tour.

Program 2 in Go Tour

Transgression answered 27/4 at 15:40 Comment(7)
The http request is going to start more goroutines.Urania
If the runtime were able to detect all deadlocks it would have solved the halting problem. It can only detect the simple case where all goroutines are in a state where no progress can be made.Urania
Importing the “net” package on macOS is sufficient to cause the detection fail. The package (or some other package imported by net) probably starts a goroutine that waits on a condition that cannot be used in deadlock detection.Artema
@Urania Go implements Communicating Sequential Processes, and the process calculi (from the 1970s) that describes it (fancy algebra) makes it possible to predict whether a program will deadlock, or livelock. If CSP constructs are all that is in play, a computer can spot deadlocks without solving the halting problem. A side benefit is that if a program can deadlock, it always will (easy to find in testing). This is an advantage over Actor Model (e.g. ZeroMQ, the Internet) which is not analysable, and cannot be proved OK via testing. However, I've no idea if Go does the maths or not.Underfoot
@bazza, go is not pure CSP, so regardless of what an be mathematically proven in a pure situation, it doesn’t apply in general. We do get the basic deadlock detection that results from CSP, but this case of waiting on external stimuli does not fall under that category.Urania
@jimb That's fair enough. A purist might consider waiting for an external stimulus to be a different sort of deadlock; the program will come back to life if the external stimulus is delivered (accepted; it may never arrive). Whereas a CSP deadlock is unrecoverable; the program is never going to run again and has reached its end state (which is probably a mistake). It's interesting to wonder what external stimulus is being waited for, having imported the net package. The DNS resolver? The docs suggest DNS in go on macs is different to other *nixes.Underfoot
@bazza, in the case of the example above it's more obvious, because the http.Get call is usually going to result in a network connection with read/write goroutines. The case that Cerise Limón mentioned of just importing the net package, that is the result of the internal infrastructure to trampoline name resolution to the host resolver via cgo. Building without that via the netgo tag will avoid the behavior.Urania

© 2022 - 2024 — McMap. All rights reserved.