Golang:来自C代码的恐慌(致命错误),无法恢复

时间:2014-10-05 14:37:01

标签: c go

我正在将Leptonica C库导入我的Go应用程序并使用它来旋转和裁剪图像。

由于某种原因,它会随机产生恐慌。我的意思是随机的,因为我只是在这一点进行测试,所以我在测试期间反复处理完全相同的20个图像,并且反复使用相同的旋转/裁剪指令。通常它可以工作但是大约1/50倍它会对图像中的随机图像造成恐慌,尽管通常是图像上较少的图像(大多数是白色图像)。

恐慌是:

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
}

0 个答案:

没有答案