Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Consistently crashing on heavy go-routine usage #19581

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

Comments

Projects
None yet
4 participants
@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

This comment has been minimized.

Copy link
Member

dominikh commented Mar 16, 2017

  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

This comment has been minimized.

Copy link
Member

bradfitz commented Mar 16, 2017

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.

@bradfitz bradfitz closed this Mar 16, 2017

@golang golang locked and limited conversation to collaborators Mar 16, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.