Golang:C代码出现死机(致命错误),无法恢复
我正在将Leptonica C库导入我的Go应用程序,并使用它旋转和裁剪图像 出于某种原因,它随机产生恐慌。我的意思是随机的,因为我只是在这一点上进行测试,所以我在测试过程中使用完全相同的旋转/裁剪指令重复处理完全相同的20幅图像。通常它可以工作,但大约有1/50倍会在图像中随机出现恐慌,尽管通常情况下图像上的恐慌较少(大部分为白色图像) 给出的恐慌是:Golang:C代码出现死机(致命错误),无法恢复,c,go,C,Go,我正在将Leptonica C库导入我的Go应用程序,并使用它旋转和裁剪图像 出于某种原因,它随机产生恐慌。我的意思是随机的,因为我只是在这一点上进行测试,所以我在测试过程中使用完全相同的旋转/裁剪指令重复处理完全相同的20幅图像。通常它可以工作,但大约有1/50倍会在图像中随机出现恐慌,尽管通常情况下图像上的恐慌较少(大部分为白色图像) 给出的恐慌是: fatal error: unexpected signal during runtime execution [signal 0xb cod
fatal error: unexpected signal during runtime execution
[signal 0xb code=0x2 addr=0x7fed87890340 pc=0x7fed91e2de3e]
runtime stack:
runtime: unexpected return pc for runtime.sigpanic called from 0x7fed91e2de3e
runtime.throw(0x88bcc5)
/usr/local/go/src/pkg/runtime/panic.c:520 +0x69
runtime: unexpected return pc for runtime.sigpanic called from 0x7fed91e2de3e
runtime.sigpanic()
/usr/local/go/src/pkg/runtime/os_linux.c:222 +0x3d
goroutine 16 [syscall]:
runtime.cgocall(0x401550, 0xc213ca98e8)
/usr/local/go/src/pkg/runtime/cgocall.c:143 +0xe5 fp=0xc213ca98d0 sp=0xc213ca9888
private/leptonica._Cfunc_pixClipRectangle(0x7fed8788ff00, 0x7fed8788ffd0, 0x0, 0x8c2a28)
private/leptonica/_obj/_cgo_defun.c:80 +0x31 fp=0xc213ca98e8 sp=0xc213ca98d0
private/leptonica.(*goPix).Crop(0xc20af90000, 0x900, 0x90, 0x4d8, 0x9a8, 0x4202c1, 0x0, 0x0)
/home/go/src/private/leptonica/leptonica.go:154 +0xd8 fp=0xc213ca9960 sp=0xc213ca98e8
main.(*pageStruct).transformOriginal(0xc20805ae10, 0xc224772000, 0x69, 0x1)
/home/root/go/frankenstein.go:1353 +0x30d fp=0xc213ca99c8 sp=0xc213ca9960
main.(*pageStruct).transformOriginalWithRecover(0xc20805ae10, 0xc224772000, 0x69, 0x1, 0x0, 0x5, 0x0, 0x0)
/home/root/go/frankenstein.go:1403 +0xe1 fp=0xc213ca9a38 sp=0xc213ca99c8
main.(*book).processPages(0xc208a90000, 0x0, 0x0)
/home/root/go/frankenstein.go:1542 +0x305 fp=0xc213ca9e48 sp=0xc213ca9a38
main.main()
/home/root/go/frankenstein.go:1970 +0x3f5 fp=0xc213ca9f50 sp=0xc213ca9e48
runtime.main()
/usr/local/go/src/pkg/runtime/proc.c:247 +0x11a fp=0xc213ca9fa8 sp=0xc213ca9f50
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1445 fp=0xc213ca9fb0 sp=0xc213ca9fa8
created by _rt0_go
/usr/local/go/src/pkg/runtime/asm_amd64.s:97 +0x120
goroutine 19 [finalizer wait]:
runtime.park(0x424c70, 0x8a9c08, 0x88e8a9)
/usr/local/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x8a9c08, 0x88e8a9)
/usr/local/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
/usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1445
goroutine 33 [syscall, 7 minutes]:
runtime.goexit()
/usr/local/go/src/pkg/runtime/proc.c:1445
我已尝试从中恢复,并使用名为transformOriginalWithRecover的函数重做transformOriginal函数。它实现延迟恢复,然后调用transformOriginal。不幸的是,这不起作用
我的恢复函数调用了通过C调用Leptonica的函数:
func (p *pageStruct) transformOriginalWithRecover(savefile string, detectOrientation bool, ontry, maxtries int) error {
var err error = nil
defer func() {
if r := recover(); r != nil {
ontry++
if ontry >= maxtries {
err = errors.New(`Failed to transform original.`)
} else {
if verbose {
fmt.Println(`Transform panicked. Recovered and retrying.`)
}
p.transformOriginalWithRecover(savefile, detectOrientation, ontry, maxtries)
}
}
}()
p.transformOriginal(savefile, detectOrientation)
return err
}
我用p.transformOriginalWithRecover(filename,true,0,5)
调用它,表明它应该在放弃之前尝试恢复5次
你知道我如何解决这个问题,或者如何从C引发的恐慌中恢复过来吗
更新
以下是导致此问题的特定功能。恐慌随机发生在C.pixClipRectangle
内部。Leptonica剪辑图像的时间越长,这种情况发生的可能性就越大,这当然是有道理的,因为这给了GC更多的时间来决定激活
func (p *goPix) Crop(x, y, w, h int) (*goPix, error) {
startX, startY, width, height := C.l_int32(x), C.l_int32(y), C.l_int32(w), C.l_int32(h)
box := C.boxCreateValid(startX, startY, width, height)
if box == nil {
box = C.boxCreateValid(startX, startY, width, height)
if box == nil {
return p, errors.New(`Unable to create box.`)
}
}
newpix := C.pixClipRectangle(p.cPix, box, nil)
if newpix != p.cPix {
p.Free()
}
C.boxDestroy(&box)
C.free(unsafe.Pointer(box))
if newpix == nil {
return nil, errors.New(`Crop failed`)
}
pix := &goPix{
cPix: newpix,
}
return pix, nil
}
你在程序上运行过竞赛条件检测器吗?没有,为什么会是竞赛条件?因为你说“有时是随机的”?好的。我将查找竞争条件并实现检测器。谢谢。另一种可能性是,如果您正在传递一个指向C的指针,该指针超出了范围,并且在cgo调用返回之前偶尔被GC’ed。