Skip to content

Commit 8740cc3

Browse files
committed
fix: acquire GIL before C→Go argument conversion in generated CGo wrappers
C.GoString (and other py2go converters) call runtime.gostring → mallocgc inside a CGo callback. If those conversions run after PyEval_SaveThread releases the GIL, Go's GC can observe a corrupted sweep-generation counter, causing "fatal error: bad sweepgen in refill" on Go ≥1.24 / macOS x86_64 (issue #370). In genFuncBody(), pre-convert each py2go argument into a local variable while the GIL is held via PyGILState_Ensure/Release, then release the GIL for the actual Go function call as before. Interface-handle arguments (ifchandle && goname == "interface{}") are excluded from pre-conversion, matching the existing callArgs switch logic to avoid type mismatches in generated code for the iface example. Also documents Idea 2 (unsafe.String zero-alloc approach) as a future defence-in-depth option in a code comment.
1 parent 55ee3fa commit 8740cc3

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

bind/gen_func.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,15 @@ func (g *pyGen) genFuncBody(sym *symbol, fsym *Func) {
287287
preConvertedArgs := map[int]string{} // arg index → temp variable name
288288
needsGILForArgs := false
289289
for _, arg := range args {
290-
if arg.sym.py2go != "" && !arg.sym.isSignature() {
290+
if arg.sym.py2go != "" && !arg.sym.isSignature() && !(ifchandle && arg.sym.goname == "interface{}") {
291291
needsGILForArgs = true
292292
break
293293
}
294294
}
295295
if needsGILForArgs {
296296
g.gofile.Printf("_gstate := C.PyGILState_Ensure()\n")
297297
for i, arg := range args {
298-
if arg.sym.py2go != "" && !arg.sym.isSignature() {
298+
if arg.sym.py2go != "" && !arg.sym.isSignature() && !(ifchandle && arg.sym.goname == "interface{}") {
299299
anm := pySafeArg(arg.Name(), i)
300300
tmpVar := fmt.Sprintf("_arg%d", i)
301301
g.gofile.Printf("%s := %s(%s)%s\n", tmpVar, arg.sym.py2go, anm, arg.sym.py2goParenEx)

0 commit comments

Comments
 (0)