dsb238100 2014-10-05 14:37
浏览 408

Golang:C代码出现严重错误(严重错误),无法恢复

I'm importing Leptonica C library into my Go app and using this for rotating and cropping an image.

For some reason it randomly produces a panic. I do mean random because I'm just testing at this point and so I'm processing exactly the same 20 images with exactly the same rotate/crop instructions repeatedly during my testing. Usually it works but around 1/50 times it will panic on a random one of the image, albeit usually one that has less on it (a mostly white image).

The panic given is:

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

I have tried to recover from this and redo the transformOriginal function with a function called transformOriginalWithRecover. Which implements a defer recover and then calls transformOriginal. Unfortunately that doesn't work.

My recovery function, which calls the function that then calls Leptonica via C is:

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
}

Which I call with p.transformOriginalWithRecover(filename, true, 0, 5) to indicate it should try to recover 5 times before giving up.

Any idea how I can either solve this or somehow recover from a panic that was instigated from C?

UPDATE

Here is the specific function that is causing this problem. The panic happens inside of C.pixClipRectangle randomly. It is more likely to happen the longer Leptonica takes to clip the image, which of course makes sense as that gives the GC more time to decide to activate.

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条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 Arduino红外遥控代码有问题
    • ¥15 数值计算离散正交多项式
    • ¥30 数值计算均差系数编程
    • ¥15 redis-full-check比较 两个集群的数据出错
    • ¥15 Matlab编程问题
    • ¥15 训练的多模态特征融合模型准确度很低怎么办
    • ¥15 kylin启动报错log4j类冲突
    • ¥15 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
    • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
    • ¥15 onvif+openssl,vs2022编译openssl64