Go language dead Loop analysis

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Recently read an article, how to locate the Golang process hang dead bug, there is such a piece of code:

package mainimport (    "fmt"    "io"    "log"    "net/http"    "runtime"    "time")func main() {    runtime.GOMAXPROCS(runtime.NumCPU())    go server()    go printNum()    var i = 1    for {        // will block here, and never go out        i++    }    fmt.Println("for loop end")    time.Sleep(time.Second * 3600)}func printNum() {    i := 0    for {        fmt.Println(i)        i++    }}func HelloServer(w http.ResponseWriter, req *http.Request) {    fmt.Println("hello world")    io.WriteString(w, "hello, world!\n")}func server() {    http.HandleFunc("/", HelloServer)    err := http.ListenAndServe(":12345", nil)    if err != nil {        log.Fatal("ListenAndServe: ", err)    }}

Run, will find print a moment after the numbers stop and we execute

curl localhost:12345

The program is stuck dead. About where the program hangs dlv is well positioned:

dlv debug hang.go

After going in and running the program, the print stops entering the dead state, which we perform ctrl C and dlv will show where the disconnection is:

received SIGINT, stopping process (will not forward signal)> main.main() ./hang.go:17 (PC: 0x12dd7c8)    12: func main() {    13:         runtime.GOMAXPROCS(runtime.NumCPU())    14:         go server()    15:         go printNum()    16:         var i = 1=>  17:         for {    18:                 // will block here, and never go out    19:                 i++    20:         }    21:         fmt.Println("for loop end")    22:         time.Sleep(time.Second * 3600)(dlv)

But I still do not understand, do not understand the place mainly because:

    • I read two more articles. Brief analysis of Goroutine scheduling example and also talk about the Goroutine scheduler, written by the same author Tony Bai, writes very well. The second article explains the goroutine of the schedule and the number of CPUs (no more explanations, suggest everyone), my Mac is a dual core four thread (here does not understand the classmate self-Google CPU Hyper-threading), Go version is 1.9, theoretically can run 4 goroutine without regard to the dead loop, a dead loop up to a CPU killed, the above code only 3 Goroutine, and they appear to hang.
    • In theory, not my subjective speculation, I ran 1 an example in the first article:
package mainimport (    "fmt"    "time")func deadloop() {    for {    }}func main() {    go deadloop()    for {        time.Sleep(time.Second * 1)        fmt.Println("I got scheduled!")    }}

The above code has two goroutine, one is main goroutine , one is deadloop goroutine , run time deadloop gouroutine will not main goroutine affect, printing has been continuing, the author's article explains the reason.

    • How to locate the Golang process hang dead bug This article mentioned gcwaiting , however no explanation.

In how to locate the Golang process hang dead bug has such a passage:

Because there is no function call in the For loop, the compiler does not insert the dispatch code, so the goroutine that executes the FOR loop has no way to be paged out, and when it encounters a GC during the loop, it is stuck in the gcwaiting phase, and the entire process will always hang dead on this loop. And no longer respond externally.

This is actually our first code card dead reason, but also our second code is not the cause of the death, is on gc !

We look at an article, Golang garbage Collection (GC) mechanism, this article is very short, but every sentence is important:

  1. Set gcwaiting=1, which checks for this state before each G task, if so, the current m is dormant;
  2. If this m is running a long-time G-task, what if it will wait for the G-task to switch itself? Such words can wait 10ms ah, can't wait! Resolute can't wait!
    So the preemption flag (similar to the previous one) will be issued, so that the current G task is interrupted and the next G task is run, it will go to the 1th step.

So if this is running a dead loop without function calls, the GC also issued a preemption tag, but if the dead loop has no function call, there is no place to be marked, cannot be preempted, it can only be set gcwaiting=1 , and m is not dormant , stop the world stuck (deadlock), gcwaiting has been 1, the whole program is stuck!

Here has actually explained the first code of the phenomenon, the second code why not hang to believe you can also guess: the code does not trigger gc! Let's trigger it manually:

package mainimport (    "fmt"    "log"    "net/http"    _ "net/http/pprof"    // "runtime"    "time")func deadloop() {    for {    }}func main() {    go func() {        log.Println(http.ListenAndServe("localhost:6060", nil))    }()    go deadloop()    i := 3    for {        time.Sleep(time.Second * 1)        i--        fmt.Println("I got scheduled!")        if i == 0 {            runtime.GC()        }    }}

Will find that after printing 3 lines, the program is also stuck, bingo?

Let's see gcwaiting if it equals 1:

$ go Build hang2.go$ godebug= "schedtrace=300,scheddetail=1"./hang2sched 2443ms:gomaxprocs=4 idleprocs=3 threads=7 Spinningthreads=0 idlethreads=2 runqueue=0 gcwaiting=0 nmidlelocked=0 stopwait=0 sysmonwait=0 P0:status=1 schedtick=4 s Yscalltick=5 m=5 runqsize=0 gfreecnt=1 p1:status=0 schedtick=14 syscalltick=0 m=-1 runqsize=0 gfreecnt=0 p2:status=0 s  Chedtick=3 syscalltick=4 m=-1 runqsize=0 gfreecnt=0 ... SCHED 2751ms:gomaxprocs=4 idleprocs=0 threads=7 spinningthreads=0 idlethreads=2 runqueue=0 gcwaiting=1 nmidlelocked=0 Stopwait=1 sysmonwait=0 p0:status=1 schedtick=4 syscalltick=5 m=5 runqsize=0 gfreecnt=1 p1:status=3 schedtick=14 Sysca Lltick=0 m=-1 runqsize=0 gfreecnt=0 p2:status=3 schedtick=3 syscalltick=10 m=-1 runqsize=0 gfreecnt=0 p3:status=3 sche Dtick=1 syscalltick=26 m=0 runqsize=0 gfreecnt=0 m6:p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 Help Gc=0 spinning=false blocked=false lockedg=-1 m5:p=0 curg=19 mallocing=0 throwing=0 preemptoff=Locks=0 dying=0 HELPG 

Code sincerity does not bully me also!

Resources

    • How to locate the Golang process hang dead bug
    • Brief analysis of Goroutine dispatching example
    • Also talk about Goroutine scheduler
    • Golang garbage Collection (GC) mechanism

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.