Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Consistently crashing on heavy go-routine usage #19581

Closed
necro351 opened this issue Mar 16, 2017 · 2 comments
Closed

Consistently crashing on heavy go-routine usage #19581

necro351 opened this issue Mar 16, 2017 · 2 comments

Comments

@necro351
Copy link

necro351 commented Mar 16, 2017

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.8 linux/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/rspillane/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build478482962=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

I ran and built the included program like this:
GOMAXPROCS=4 GODEBUG=schedtrace=1000 ./threads

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

rspillane@ubuntu:/tmp$ cat threads.go 
package main

import (
	"time"
)

func main() {
	baubles := make(chan bool, 1024)
	for {
		baubles <- true
		go func() {
			busycounter := 0
			for {
				select {
				case <-time.After(time.Millisecond):
					break
				default:
					busycounter += 1
				}
			}
			<-baubles
		}()
	}
}

What did you expect to see?

It should run forever and consume all my CPU and a little RAM (1-4KB per thread times 1024 threads, so several MBs).

What did you see instead?

The kernel would kill my process sometimes. Other times the process would crash with many many backtraces because it ran out of memory somewhere else. Back-trace of the many-many-backtrace case included (when the kernel kills it it just prints 'Killed').

threads.go puking.txt

@dominikh
Copy link
Member

  1. the break is breaking out of the select, not the for loop
  2. on each iteration of the inner loop, you will create a timer, go into the default case, then repeat the inner loop, which allocates an immense number of timers until you run out of memory.

For questions about Go, see https://golang.org/wiki/Questions.

@bradfitz
Copy link
Contributor

Dup of #15698 etc

See also: #8895 and #8898

Workaround: don't use time.After and use a time.NewTimer and defer a Stop of it instead.

@golang golang locked and limited conversation to collaborators Mar 16, 2018
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Projects
None yet
Development

No branches or pull requests

4 participants