sbinet / go-python

naive go bindings to the CPython2 C-API
Other
1.53k stars 138 forks source link

fatal error: unexpected signal during runtime execution #31

Closed tangleiao closed 5 years ago

tangleiao commented 8 years ago

hi sbinet: While using go-python , occurred the error "fatal error: unexpected signal during runtime execution". The error looks like c programming error. I am using python 2.7 Can you have any suggestion?

Thank you.

tangleiao commented 8 years ago

fatal error: unexpected signal during runtime execution [signal 0xb code=0x1 addr=0x48 pc=0x7f468752708c]

runtime stack: runtime.gothrow(0x106ee10, 0x2a) /usr/local/go/src/runtime/panic.go:503 +0x8e runtime.sigpanic() /usr/local/go/src/runtime/sigpanic_unix.go:14 +0x5e

goroutine 36 [syscall, locked to thread]: runtime.cgocall_errno(0x416950, 0xc2083261a0, 0x0) /usr/local/go/src/runtime/cgocall.go:130 +0xf5 fp=0xc208326180 sp=0xc208326158 github.com/sbinet/go-python._Cfunc_PyImport_ImportModule(0x7f46640008c0, 0x0) /data/tlt/go/src/github.com/sbinet/go-python/:758 +0x44 fp=0xc2083261a0 sp=0xc208326180 github.com/sbinet/go-python.PyImport_ImportModule(0xef93d0, 0x7, 0x0) /data/tlt/go/src/github.com/sbinet/go-python/utilities.go:166 +0x6d fp=0xc2083261d8 sp=0xc2083261a0 github.com/grafana/grafana/pkg/middleware.IsAlarmSignedIn(0xc2081c60c0, 0xc208326328) /data/tlt/go/src/github.com/grafana/grafana/pkg/middleware/auth.go:119 +0x233 fp=0xc2083262d8 sp=0xc2083261d8 github.com/grafana/grafana/pkg/middleware.func·002(0xc2081c60c0) /data/tlt/go/src/github.com/grafana/grafana/pkg/middleware/auth.go:81 +0x31 fp=0xc2083262f8 sp=0xc2083262d8 runtime.call16(0xc208352490, 0xc2080393c0, 0x800000008) /usr/local/go/src/runtime/asm_amd64.s:401 +0x45 fp=0xc208326310 sp=0xc2083262f8 reflect.Value.call(0xbe0be0, 0xc208352490, 0x13, 0xee31b0, 0x4, 0xc2083380a0, 0x1, 0x1, 0x0, 0x0, ...) /usr/local/go/src/reflect/value.go:419 +0x10e5 fp=0xc208326628 sp=0xc208326310 reflect.Value.Call(0xbe0be0, 0xc208352490, 0x13, 0xc2083380a0, 0x1, 0x1, 0x0, 0x0, 0x0) /usr/local/go/src/reflect/value.go:296 +0xbc fp=0xc208326688 sp=0xc208326628 github.com/Unknwon/macaron/inject.(_injector).Invoke(0xc208358aa0, 0xbe0be0, 0xc208352490, 0x0, 0x0, 0x0, 0x0, 0x0) /data/tlt/go/src/github.com/Unknwon/macaron/inject/inject.go:102 +0x3c7 fp=0xc208326798 sp=0xc208326688 github.com/Unknwon/macaron.(_Context).run(0xc2081f0fc0) /data/tlt/go/src/github.com/Unknwon/macaron/context.go:113 +0x95 fp=0xc208326860 sp=0xc208326798 github.com/Unknwon/macaron.(*Context).Next(0xc2081f0fc0) /data/tlt/go/src/github.com/Unknwon/macaron/context.go:104 +0x33 fp=0xc208326870 sp=0xc208326860 github.com/grafana/grafana/pkg/middleware.func·009(0xc2081c60c0) /data/tlt/go/src/github.com/grafana/grafana/pkg/middleware/session.go:71 +0x37 fp=0xc2083268f0 sp=0xc208326870 runtime.call16(0xc208352480, 0xc2080393b8, 0x800000008)

sbinet commented 8 years ago

could you provide me with an as simple as possible reproducer?

jjjachyty commented 6 years ago

So do I,when i use goroutine to pyObject.CallFunction(xx,xx)

sbinet commented 6 years ago

@jjjachyty could you provide me with an as simple as possible reproducer?

jjjachyty commented 6 years ago

@sbinet I've been using thrift RPC service replace this way,you can write go bench test to call pyObject.CallFunction(xx,xx),This error will appear

sbinet commented 6 years ago

I believe you, of course, but having a minimal reproducer would greatly help debug the exact same issue you have.

jjjachyty commented 6 years ago

@sbinet main.go

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/sbinet/go-python"
)

func init() {
    err := python.Initialize()
    if err != nil {
        panic(err.Error())
    }
}

func main() {

    for index := 0; index < 5; index++ {
        go call()
    }
    time.Sleep(20 * time.Second)
}

func call() {
    flag := python.PyRun_SimpleString("import sys")
    fmt.Println("flag", flag)
    python.PyRun_SimpleString("sys.path.append('.')")

    m := python.PyImport_ImportModule("produrce")

    if m == nil {
        log.Fatalf("could not import 'kwargs'\n")
    }

    callProcedure := m.GetAttrString("callProcedure")
    if callProcedure == nil {
        log.Fatalf("could not getattr(kwargs, 'callProcedure')\n")
    }

    // keyword arguments
    url := python.PyString_FromString("tjlrm/tjlrm@172.168.171.200:1521/xe")
    kw := python.PyLong_FromLong(1519291183)
    name := python.PyString_FromString("PROC_TEST")

    out := callProcedure.CallFunction(url, name, kw)
    if out == nil {
        log.Fatalf("error calling foo(*args, **kwargs)\n", out)
    }
    returnFlag := python.PyTuple_GetItem(out, 0)
    returnMsg := python.PyTuple_GetItem(out, 1)

    fmt.Println("--------", python.PyLong_AsLong(returnFlag), python.PyString_AsString(returnMsg))
    //fmt.Printf("%s\n", str)
}

produrce.py

#! /usr/bin/env python
# -*- coding: utf-8 -*-
import cx_Oracle
import time
import os
import datetime
import sys

def callProcedure(url,prdocedureName,unixDate):
    os.environ['NLS_LANG'] = "American_America.AL32UTF8"
    try:
        conn = cx_Oracle.connect(url)
        cursor = conn.cursor()
        asofdate = datetime.datetime.strptime(time.strftime("%Y-%m-%d", time.localtime(unixDate)), '%Y-%m-%d')
        param4 = cursor.var(cx_Oracle.NUMBER)  # plsql出参

        param5 = cursor.var(cx_Oracle.STRING)  # plsql出参

        # args.append(param4,param5)
        # 调用存储过程
        cursor.callproc(prdocedureName, [asofdate,param4,param5])  # ['Nick', 'Nick, Good Morning!']

        return param4.getvalue(),param5.getvalue()
    except Exception as e:
        print("错误",e)
        return False,False,e.__str__()
    finally:
    # 资源关闭
        cursor.close()
        conn.close()

then this error will be appear


fatal error: unexpected signal during runtime execution
fatal error: unexpected signal during runtime execution
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0xb01dfacedebac1e pc=0x7fff550b22c7]

runtime stack:
runtime.throw(0x40de253, 0x2a)
        /DATA/Work/CODE/GO/GOROOT/go/src/runtime/panic.go:605 +0x95
runtime.sigpanic()
        /DATA/Work/CODE/GO/GOROOT/go/src/runtime/signal_unix.go:351 +0x2b8

goroutine 6 [syscall, locked to thread]:
runtime.cgocall(0x40a30f0, 0xc4200a8e88, 0xc4200a8e90)
        /DATA/Work/CODE/GO/GOROOT/go/src/runtime/cgocall.go:132 +0xe4 fp=0xc4200a8e58 sp=0xc4200a8e18 pc=0x4004314```
sbinet commented 6 years ago

thanks @jjjachyty

I see an invalid use of go-python (well, the CPython API, really):

you call concurrently multiple CPython API functions (through go call()). CPython is notoriously known for its GIL (the Global Interpreter Lock) that has to be held whenever one needs to make a call to the CPython API.

you need to make sure only one thread is calling back into CPython: https://docs.python.org/2/c-api/init.html#thread-state-and-the-global-interpreter-lock

yanchenghust commented 5 years ago

I have the same problems, here is my solution: after python.Initialize(),do pyThreadState = python.PyEval_SaveThread()。 Each time you access to the python C API,do as follows:

python.PyEval_RestoreThread(pyThreadState)
// your code ...  
pyThreadState = python.PyEval_SaveThread()

here is my sample code:

var pyModule, ut, exec, compile *python.PyObject
var pyThreadState *python.PyThreadState
var PyStr = python.PyString_FromString
var GoStr = python.PyString_AS_STRING

func InitPy(pyModulePath string) {
    err := python.Initialize()
    if err != nil {
        panic(err.Error())
    }
    pyModule = ImportModule(pyModulePath, "python_runtime")
    ut = pyModule.GetAttrString("ut")
    exec = pyModule.GetAttrString("exec_code")
    compile = pyModule.GetAttrString("compile")
    logs.Debug("pyModule=%#v, ut=%#v, exec=%#v, compile=%#v", pyModule, ut, exec, compile)
    pyThreadState = python.PyEval_SaveThread()
}
func FinalizePy() {
    python.PyEval_RestoreThread(pyThreadState)
    python.Finalize()
    logs.Debug("finalized")
    logs.Flush()
}
func (r PythonRuntime) RunUt(ctx context.Context, code, input, output string) (*model.UtResult, error) {
    python.PyEval_RestoreThread(pyThreadState)
    utArgs := python.PyTuple_New(3)
    if output == "" {
        output = "None"
    }
    python.PyTuple_SetItem(utArgs, 0, PyStr(code))
    python.PyTuple_SetItem(utArgs, 1, PyStr(input))
    python.PyTuple_SetItem(utArgs, 2, PyStr(output))
    utResult := ut.Call(utArgs, python.Py_None)
    ret := &model.UtResult{}
    ret.Success = python.PyInt_AS_LONG(python.PyDict_GetItemString(utResult, "success")) == 1
    ret.ErrMsg = GoStr(python.PyDict_GetItemString(utResult, "msg"))
    ret.ExecOutput = GoStr(python.PyDict_GetItemString(utResult, "output"))
    pyThreadState = python.PyEval_SaveThread()
    return ret, nil
}
sbinet commented 5 years ago

yes, @yanchenghust , that's another way to deal with the GIL. marking this as "resolved".

kingangelAOA commented 5 years ago

goroutine 2002412 [syscall]: github.com/sbinet/go-python._Cfunc_PyEval_RestoreThread(0x28805e0) _cgo_gotypes.go:2642 +0x41 github.com/sbinet/go-python.PyEval_RestoreThread.func1(0xc00de0b8a0) /home/jyan/work/go_work/src/github.com/sbinet/go-python/python.go:64 +0x5e github.com/sbinet/go-python.PyEval_RestoreThread(0xc00de0b8a0) /home/jyan/work/go_work/src/github.com/sbinet/go-python/python.go:64 +0x2b kyara.(PythonScriptList).Run(0xc00000e180, 0x57cdee, 0x4, 0x57d15e, 0x6, 0x0, 0x0) /home/jyan/work/go_work/src/kyara/script.go:60 +0x3c kyara.TestHigh.func1(0x0, 0x0) /home/jyan/work/go_work/src/kyara/script_test.go:71 +0x58 kyara.(Pool).Start.func2.1(0xc00006e2a0, 0x16c043aebb2, 0xc0000243c8) /home/jyan/work/go_work/src/kyara/pool.go:63 +0x2f created by kyara.(*Pool).Start.func2 /home/jyan/work/go_work/src/kyara/pool.go:62 +0x119

when i set 6000 goroutines, and Run this func

func (p *PythonScriptList) Run(moduleName, methodArgs string) error { python.PyEval_RestoreThread(pyThreadState) if module, ok := p.moduleMap[moduleName]; ok { method, argsList, err := getMethodArgs(methodArgs) if err != nil { return err } result := module.CallMethod(method, argsList...) //fmt.Println(python.PyString_AsString(result)) defer result.DecRef() } else { return ErrModuleNotExist } pyThreadState = python.PyEval_SaveThread() return nil }

dhanush commented 4 years ago

I am also trying the same as @yanchenghust and I still get the same error. Is this type of conversion important as well

GoStr(python.PyDict_GetItemString(utResult, "msg"))

I have lot of such variables not converted. Instead I use

pySum := python.PyDict_GetItemString(result, "sum")
goSum := python.PyFloat_AsDouble(pySum),

Could this be the issue?