Skip to content

Commit

Permalink
cmd/cgo: disable #cgo noescape/nocallback until Go 1.23
Browse files Browse the repository at this point in the history
Go 1.21 and earlier do not understand this line, causing
"go mod vendor" of //go:build go1.22-tagged code that
uses this feature to fail.

The solution is to include the go/build change to skip over
the line in Go 1.22 (making "go mod vendor" from Go 1.22 onward
work with this change) and then wait to deploy the cgo change
until Go 1.23, at which point Go 1.21 and earlier will be unsupported.

For #56378.
Fixes #63293.

Change-Id: Ifa08b134eac5a6aa15d67dad0851f00e15e1e58b
Reviewed-on: https://go-review.googlesource.com/c/go/+/539235
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
  • Loading branch information
rsc committed Nov 2, 2023
1 parent 5622a4b commit 607e020
Show file tree
Hide file tree
Showing 8 changed files with 11 additions and 47 deletions.
19 changes: 1 addition & 18 deletions doc/go1.22.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,7 @@ <h3 id="go-command">Go command</h3>

<h3 id="cgo">Cgo</h3>

<p><!-- CL 497837 --> The special comment that precedes
<code>import</code> <code>"C"</code> may now include two
new <code>#cgo</code> directives.
<ul>
<li>
<code>#cgo</code> <code>noescape</code> <code>cFunctionName</code>
tells cgo that Go pointers passed to the C function
<code>cFunctionName</code> do not escape.
</li>
<li>
<code>#cgo</code> <code>nocallback</code> <code>cFunctionName</code>
tells cgo that the C function <code>cFunctionName</code> does
not call any Go functions.
</li>
</ul>
See <a href="/cmd/cgo#hdr-Optimizing_calls_of_C_code">the <code>cgo</code>
documentation</a> for more details.
</p>
<!-- CL 497837 reverted -->

<h2 id="runtime">Runtime</h2>

Expand Down
24 changes: 0 additions & 24 deletions src/cmd/cgo/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,30 +420,6 @@ passing uninitialized C memory to Go code if the Go code is going to
store pointer values in it. Zero out the memory in C before passing it
to Go.
# Optimizing calls of C code
When passing a Go pointer to a C function the compiler normally ensures
that the Go object lives on the heap. If the C function does not keep
a copy of the Go pointer, and never passes the Go pointer back to Go code,
then this is unnecessary. The #cgo noescape directive may be used to tell
the compiler that no Go pointers escape via the named C function.
If the noescape directive is used and the C function does not handle the
pointer safely, the program may crash or see memory corruption.
For example:
// #cgo noescape cFunctionName
When a Go function calls a C function, it prepares for the C function to
call back to a Go function. the #cgo nocallback directive may be used to
tell the compiler that these preparations are not necessary.
If the nocallback directive is used and the C function does call back into
Go code, the program will panic.
For example:
// #cgo nocallback cFunctionName
# Special cases
A few special C types which would normally be represented by a pointer
Expand Down
2 changes: 2 additions & 0 deletions src/cmd/cgo/gcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ func (f *File) ProcessCgoDirectives() {
directive := fields[1]
funcName := fields[2]
if directive == "nocallback" {
fatalf("#cgo nocallback disabled until Go 1.23")
f.NoCallbacks[funcName] = true
} else if directive == "noescape" {
fatalf("#cgo noescape disabled until Go 1.23")
f.NoEscapes[funcName] = true
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/cmd/cgo/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ int add(int x, int y) {
// escape vs noescape
#cgo noescape handleGoStringPointerNoescape
// TODO(#56378): enable in Go 1.23:
// #cgo noescape handleGoStringPointerNoescape
void handleGoStringPointerNoescape(void *s) {}
void handleGoStringPointerEscape(void *s) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
package main

/*
// ERROR MESSAGE: #cgo noescape noMatchedCFunction: no matched C function
// TODO(#56378): change back to "#cgo noescape noMatchedCFunction: no matched C function" in Go 1.23
// ERROR MESSAGE: #cgo noescape disabled until Go 1.23
#cgo noescape noMatchedCFunction
*/
import "C"
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/crash_cgo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,7 @@ func TestNeedmDeadlock(t *testing.T) {
}

func TestCgoNoCallback(t *testing.T) {
t.Skip("TODO(#56378): enable in Go 1.23")
got := runTestProg(t, "testprogcgo", "CgoNoCallback")
want := "function marked with #cgo nocallback called back into Go"
if !strings.Contains(got, want) {
Expand All @@ -762,6 +763,7 @@ func TestCgoNoCallback(t *testing.T) {
}

func TestCgoNoEscape(t *testing.T) {
t.Skip("TODO(#56378): enable in Go 1.23")
got := runTestProg(t, "testprogcgo", "CgoNoEscape")
want := "OK\n"
if got != want {
Expand Down
3 changes: 1 addition & 2 deletions src/runtime/testdata/testprogcgo/cgonocallback.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ package main
// But it do callback to go in this test, Go should crash here.

/*
#cgo nocallback runCShouldNotCallback
// TODO(#56378): #cgo nocallback runCShouldNotCallback
extern void runCShouldNotCallback();
*/
import "C"
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/testdata/testprogcgo/cgonoescape.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ package main
// 2. less than 100 new allocated heap objects after invoking withoutNoEscape 100 times.

/*
#cgo noescape runCWithNoEscape
// TODO(#56378): #cgo noescape runCWithNoEscape
void runCWithNoEscape(void *p) {
}
Expand Down

0 comments on commit 607e020

Please sign in to comment.