go-python / go-python/gopy

Returning string from Python callback to Go - and PyBytes_AsString() SIGSEGV

Đang mở
#366 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Go
Star
2.3k
Fork
136
Merge trung bình
14 phút
Pull request đã merge (30 ngày)
2

Mô tả

Hi,

Thanks for the great tool!

# Description

Trying to return a string from Python callback to Go - and getting SIGSEGV:

```
> python test.py
fs.CallBack(22, cbfun)...
in python cbfun: FieldI: 42 FieldS: str field ival: 22 sval: str field
fs.CallBackIf(22, cbfunif)...
in python cbfunif: FieldI: 42 FieldS: str field ival: 22 ifval: str field
fs.CallBackRval(22, cbfunrval)...
in python cbfunrval: FieldI: 42 FieldS: str field ival: 22 ifval: str field
```
(nothing more in output, literally)

Gdb shows more:

```
(gdb) back
#0 0x000055b7519d2627 in PyErr_Format ()
#1 0x000055b7519003a6 in ?? ()
#2 0x00007f330e0d0dab in _cgo_86d28a1f6e85_Cfunc_PyBytes_AsString () from /app/out/_funcs.cpython-310-x86_64-linux-gnu.so
#3 0x00007f330e098c41 in runtime.asmcgocall () at /usr/local/go/src/runtime/asm_amd64.s:923
#4 0x000000c000006700 in ?? ()
#5 0x00007ffee5d3e9a0 in ?? ()
#6 0x000055b763a8eee0 in ?? ()
#7 0x000000c000044008 in ?? ()
#8 0x00007ffee5d3ea58 in ?? ()
#9 0x00007f330e0a0c21 in crosscall2 () at /usr/local/go/src/runtime/cgo/asm_amd64.s:43
#10 0x00007f330e0d0c07 in funcs_FunStruct_CallBackRval () from /app/out/_funcs.cpython-310-x86_64-linux-gnu.so
#11 0x00007f330e0d5176 in _wrap__funcs_funcs_FunStruct_CallBackRval () from /app/out/_funcs.cpython-310-x86_64-linux-gnu.so
#12 0x000055b7519cbdae in ?? ()
#13 0x000055b7519c252b in _PyObject_MakeTpCall ()
#14 0x000055b7519bb16b in _PyEval_EvalFrameDefault ()
#15 0x000055b7519cc6ac in _PyFunction_Vectorcall ()
#16 0x000055b7519b4b2b in _PyEval_EvalFrameDefault ()
#17 0x000055b7519b1096 in ?? ()
#18 0x000055b751aa6f66 in PyEval_EvalCode ()
#19 0x000055b751ad1e98 in ?? ()
#20 0x000055b751acb79b in ?? ()
#21 0x000055b751ad1be5 in ?? ()
#22 0x000055b751ad10c8 in _PyRun_SimpleFileObject ()
#23 0x000055b751ad0d13 in _PyRun_AnyFileObject ()
#24 0x000055b751ac370e in Py_RunMain ()
#25 0x000055b751a99dfd in Py_BytesMain ()
#26 0x00007f330e733d90 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#27 0x00007f330e733e40 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#28 0x000055b751a99cf5 in _start ()
```

Trying _examples/funcs/
Just 2 changes to ret type string:

funcs.go:
```
-func (fs *FunStruct) CallBackRval(i int, fun func(fs *FunStruct, i int, v interface{}) bool) {
+func (fs *FunStruct) CallBackRval(i int, fun func(fs *FunStruct, i int, v interface{}) string) {
```

test.py:
```
in def cbfunrval(afs, ival, ifval):
- return True
+ return "some string"
```

# Versions
Gopy:
commit 1d7f3a2d29bd9f3921ff640f8e4e8908170ff3bf (HEAD -> master, tag: v0.4.10, origin/master, origin/HEAD)

Python 3.10.12 (main, Jul 29 2024, 16:56:48) [GCC 11.4.0] on linux
go version go1.23.2 linux/amd64

# The Reason
Generated out/funcs.go:

funcs_FunStruct_CallBackRval is generated to pass _fcret without type checks:
```
...
_fcret := C.PyObject_CallObject(_fun_arg, _fcargs)
C.gopy_decref(_fcargs)
C.gopy_err_handle()
C.PyGILState_Release(_gstate)
return C.GoString(C.PyBytes_AsString(_fcret))
...
```

And PyBytes_AsString - panics as _fcret is not bytes.

# Workaround

But, changing ret type to bytes - and things work fine:
test.py:
```
in def cbfunrval(afs, ival, ifval):
- return "some string"
+ return b"some string"
```

```
> python test.py
fs.CallBack(22, cbfun)...
in python cbfun: FieldI: 42 FieldS: str field ival: 22 sval: str field
fs.CallBackIf(22, cbfunif)...
in python cbfunif: FieldI: 42 FieldS: str field ival: 22 ifval: str field
fs.CallBackRval(22, cbfunrval)...
in python cbfunrval: FieldI: 42 FieldS: str field ival: 22 ifval: str field
got return value: some string
fs.CallBack(32, cls.ClassFun)...
in python class fun: FieldI: 42 FieldS: str field ival: 32 sval: str field
cls.CallSelf...
in python class fun: FieldI: 42 FieldS: str field ival: 77 sval: str field
fs.ObjArg with nil
got nil
fs.ObjArg with fs
ofs FieldI: 42 FieldS: str field
OK
```

# Fix
So, need to test-cover PyBytes_AsString calls with more types.

# Thank you!

Hướng dẫn đóng góp

Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này

Hướng nghiên cứu

Reproduce the failure from _examples/funcs/funcs.go and test.py, then inspect generated out/funcs.go around funcs_FunStruct_CallBackRval and its PyBytes_AsString call. Add test coverage for the relevant return types and verify that a Python string callback completes without SIGSEGV while the existing bytes case still works.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
go, python
Lĩnh vực
api, tooling
Loại issue
Lỗi
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
48/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.