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

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

Open
nickeygit opened this issue Nov 25, 2024 · 0 comments

Comments

@nickeygit
Copy link

nickeygit commented Nov 25, 2024

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 1d7f3a2 (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!

@nickeygit nickeygit changed the title Returning string from Python callback - and PyBytes_AsString() SIGSEGV Returning string from Python callback to Go - and PyBytes_AsString() SIGSEGV Nov 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant