Skip to content

runtime: morestack on g0 when C calls Go with deep stack #59294

Closed
@cherrymui

Description

@cherrymui

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

tip (d49b11b)

Does this issue reproduce with the latest release?

No

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

linux/amd64

What did you do?

Build a Go c-archive, call the Go function from C.

x.go

package main

import "C"

func main() {}

//export GoF
func GoF() {}

c.c

#include "x.h"

void callGoFWithDeepStack(int n) {
	if (n > 0)
		callGoFWithDeepStack(n - 1);
	GoF();
}

int main() {
	GoF();                        // call GoF without using much stack
	callGoFWithDeepStack(100000); // call GoF with a deep stack
}
$ go build -buildmode=c-archive x.go 
$ cc -O0 c.c x.a # don't optimize out my recursion
$ ./a.out

What did you expect to see?

Run without error.

What did you see instead?

fatal: morestack on g0

This is a regression from CL https://golang.org/cl/392854 . The first time when C calls into Go, we create an M and a g0. We compute a stack bound using the current SP. We don't know how big the C stack is, so we simply assume 32K https://cs.opensource.google/go/go/+/master:src/runtime/proc.go;l=1937-1946
Previously, when the Go function returns to C, we drop the M. And the next time C calls into Go, we put a new stack bound on the g0 based on the current SP.
After the CL, we don't drop the M, so the next time C calls into Go, we reuse the same g0, without recomputing the stack bounds. If the C code uses quite a bit of stack before calling into Go, the SP may be well below the 32K stack bound we assumed, so the runtime thinks the g0 stack overflows.

We probably need to either try to get a more accurate stack bounds the first time C calling into Go, like we do in x_cgo_init https://cs.opensource.google/go/go/+/master:src/runtime/cgo/gcc_linux_amd64.c;l=46 , or recompute the g0 stack bounds based on the current SP each time when C calls into Go.

Metadata

Metadata

Assignees

Labels

FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions