bakape / thumbnailer

Go media thumbnailer
MIT License
154 stars 36 forks source link

Accessing member of nil struct cause deadlock when thumbnailer is imported #8

Closed Kagami closed 6 years ago

Kagami commented 7 years ago

This is very strange issue and might be caused by tons of reasons and maybe only specific to my system. But I'm just curious, can you reproduce it.

Minimal go program:

package main

import (
    "fmt"
    "github.com/bakape/thumbnailer"
)

type A struct {
    b *B
}

type B struct {
    c int
}

func main() {
    a := A{nil}
    fmt.Println(a.b.c)  // <- should panic here
    fmt.Println(thumbnailer.Dims{})
}

On my system it deadlocks. If I either remove thumbnailer import or .c in print, everything is ok.

bakape commented 7 years ago

Can confirm this happening. I've actually run into this before, but did not know it was related to the thumbnailer.

What are your thought's on possible causes? I might be doing something terribly wrong with the unsafe go in the thumbnailer (don't know how it can corrupt the entire package) or it might actually be a bug in the Go runtime.

And it's seems like it's not a deadlock, but an infinite loop somewhere.

Kagami commented 7 years ago

but did not know it was related to the thumbnailer

Yea, I encountered this behavior with meguca and nailed it down to the thumbnailer import.

What are your thought's on possible causes?

Don't know, maybe it's even related to ffmpeg libs. I'm going to investigate this further to find minimal reproducable example.

bakape commented 6 years ago

Now that I think about it, this might be related to the signal handling in init.c.

Kagami commented 6 years ago

Can confirm with fixSignal(SIGSEGV) commented I get runtime error, though not the normal one.

signal 11 received but handler not on signal stack
fatal error: non-Go code set up signal handler without SA_ONSTACK flag

runtime stack:
runtime: unexpected return pc for runtime.sigtramp called from 0x7fc734525930
stack: frame={sp:0xc42006b928, fp:0xc42006b980} stack=[0xc420063878,0xc42006bc78)
000000c42006b828:  000000c42006b848  0000000000428421 <runtime.throw+129> 
000000c42006b838:  0000000000000000  0000000000000039 
000000c42006b848:  000000c42006b868  000000000043af0f <runtime.sigNotOnStack+127> 
000000c42006b858:  00000000004c241b  0000000000000039 
000000c42006b868:  000000c42006b918  000000000043a796 <runtime.sigtrampgo+790> 
000000c42006b878:  000000000000000b  000000c42006b900 
000000c42006b888:  000000c42006b980  0000000000000000 
000000c42006b898:  0000000000000000  000000c42006b928 
000000c42006b8a8:  0000000000000000  0000000000000000 
000000c42006b8b8:  0000000000000000  0000000000000000 
000000c42006b8c8:  0000000000000000  000000c420000180 
000000c42006b8d8:  0000000000000000  0000000000000000 
000000c42006b8e8:  0000000000000000  0000000000000000 
000000c42006b8f8:  0000000000000000  000000c420002000 
000000c42006b908:  0000000000000000  0000000000008000 
000000c42006b918:  000000c42006b970  0000000000452703 <runtime.sigtramp+67> 
000000c42006b928: <000000000000000b  000000c42006bab0 
000000c42006b938:  000000c42006b980  0000000000000200 
000000c42006b948:  0000000000000025  0000000000000026 
000000c42006b958:  ffffffffffffffff  000000c42006b970 
000000c42006b968:  0000000000000000  000000c42006bf78 
000000c42006b978: !00007fc734525930 >0000000000000007 
000000c42006b988:  0000000000000000  000000c420002000 
000000c42006b998:  0000000000000000  0000000000008000 
000000c42006b9a8:  0000000000000000  00007ffe6d0d7f70 
000000c42006b9b8:  0000000000000008  0000000000000246 
000000c42006b9c8:  ffffffffffffffff  0000000000000026 
000000c42006b9d8:  0000000000000025  0000000000000200 
000000c42006b9e8:  000000c420000101  0000000000000002 
000000c42006b9f8:  000000c42006bf78  0000000000000000 
000000c42006ba08:  00000000004c2ac0  0000000000000000 
000000c42006ba18:  000000c420000180  000000c42006bf18 
000000c42006ba28:  0000000000488c0b <main.main+43>  0000000000010246 
000000c42006ba38:  002b000000000033  0000000000000004 
000000c42006ba48:  000000000000000e  0000000000000000 
000000c42006ba58:  0000000000000000  000000c42006bb40 
000000c42006ba68:  0000000000000000  0000000000000000 
000000c42006ba78:  0000000000000000 
runtime.throw(0x4c241b, 0x39)
    /usr/lib/go/src/runtime/panic.go:619 +0x81
runtime.sigNotOnStack(0xb)
    /usr/lib/go/src/runtime/signal_unix.go:578 +0x7f
runtime.sigtrampgo(0xb, 0xc42006bab0, 0xc42006b980)
    /usr/lib/go/src/runtime/signal_unix.go:332 +0x316
runtime: unexpected return pc for runtime.sigtramp called from 0x7fc734525930
stack: frame={sp:0xc42006b928, fp:0xc42006b980} stack=[0xc420063878,0xc42006bc78)
000000c42006b828:  000000c42006b848  0000000000428421 <runtime.throw+129> 
000000c42006b838:  0000000000000000  0000000000000039 
000000c42006b848:  000000c42006b868  000000000043af0f <runtime.sigNotOnStack+127> 
000000c42006b858:  00000000004c241b  0000000000000039 
000000c42006b868:  000000c42006b918  000000000043a796 <runtime.sigtrampgo+790> 
000000c42006b878:  000000000000000b  000000c42006b900 
000000c42006b888:  000000c42006b980  0000000000000000 
000000c42006b898:  0000000000000000  000000c42006b928 
000000c42006b8a8:  0000000000000000  0000000000000000 
000000c42006b8b8:  0000000000000000  0000000000000000 
000000c42006b8c8:  0000000000000000  000000c420000180 
000000c42006b8d8:  0000000000000000  0000000000000000 
000000c42006b8e8:  0000000000000000  0000000000000000 
000000c42006b8f8:  0000000000000000  000000c420002000 
000000c42006b908:  0000000000000000  0000000000008000 
000000c42006b918:  000000c42006b970  0000000000452703 <runtime.sigtramp+67> 
000000c42006b928: <000000000000000b  000000c42006bab0 
000000c42006b938:  000000c42006b980  0000000000000200 
000000c42006b948:  0000000000000025  0000000000000026 
000000c42006b958:  ffffffffffffffff  000000c42006b970 
000000c42006b968:  0000000000000000  000000c42006bf78 
000000c42006b978: !00007fc734525930 >0000000000000007 
000000c42006b988:  0000000000000000  000000c420002000 
000000c42006b998:  0000000000000000  0000000000008000 
000000c42006b9a8:  0000000000000000  00007ffe6d0d7f70 
000000c42006b9b8:  0000000000000008  0000000000000246 
000000c42006b9c8:  ffffffffffffffff  0000000000000026 
000000c42006b9d8:  0000000000000025  0000000000000200 
000000c42006b9e8:  000000c420000101  0000000000000002 
000000c42006b9f8:  000000c42006bf78  0000000000000000 
000000c42006ba08:  00000000004c2ac0  0000000000000000 
000000c42006ba18:  000000c420000180  000000c42006bf18 
000000c42006ba28:  0000000000488c0b <main.main+43>  0000000000010246 
000000c42006ba38:  002b000000000033  0000000000000004 
000000c42006ba48:  000000000000000e  0000000000000000 
000000c42006ba58:  0000000000000000  000000c42006bb40 
000000c42006ba68:  0000000000000000  0000000000000000 
000000c42006ba78:  0000000000000000 
runtime.sigtramp(0x7, 0x0, 0xc420002000, 0x0, 0x8000, 0x0, 0x7ffe6d0d7f70, 0x8, 0x246, 0xffffffffffffffff, ...)
    /usr/lib/go/src/runtime/sys_linux_amd64.s:348 +0x43

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
    /usr/lib/go/src/runtime/asm_amd64.s:2361 +0x1 fp=0xc42005afe8 sp=0xc42005afe0 pc=0x4513d1

goroutine 1 [running]:
    goroutine running on other thread; stack unavailable
exit status 2

Btw, example program from https://github.com/rainycape/magick/issues/37 works fine with commented entire fixSignal section. So seems like that workaround is no longer needed:

package main

import (
    "log"
    "os"
    "os/signal"
    "syscall"

    _ "github.com/bakape/thumbnailer"
)

func main() {
    c := make(chan os.Signal, 1)
    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
    sig := <-c
    log.Printf("Received %+v", sig)
}
Kagami commented 6 years ago

Apparently GM now sets SA_ONSTACK on its sigaction handler by itself, commit was made just 3 days ago (I had to wait 6 hours to clone hg repo to find this, kill me please).

Now example program in first post always deadlocks. Will investigate further.

Kagami commented 6 years ago

So this is the line which cause issue: http://hg.code.sf.net/p/graphicsmagick/code/file/1e8f73a5095a/magick/magick.c#l1048

I recompiled GraphicsMagick without it and now get normal Go's panic. Seems like it somehow conflicts with Go's runtime. So it's either issue with Go or GraphicsMagick.

I'll create PR with test case and removed fixSignal code so at least users of GM 1.3.28 will get segfault and not a deadlock. Users of GM HEAD will get deadlock just like now (because GM set SA_ONSTACK by itself), but I'll create issue in GM's bugtracker so probably we will have this properly fixed (which won't require the patch to upstream GM) by the next release of GM.