Skip to content

SIGCHILD handling in Mac OS #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
quarnster opened this issue Dec 26, 2013 · 8 comments
Open

SIGCHILD handling in Mac OS #26

quarnster opened this issue Dec 26, 2013 · 8 comments

Comments

@quarnster
Copy link
Contributor

With this piece of code:

package main

import (
    "bytes"
    "github.com/niemeyer/qml"
    "log"
    "os/exec"
)

type tt struct{}

func (t *tt) Test() {
    log.Println("here")
    log.Println(exec.Command("echo", "hello").CombinedOutput())
    log.Println("But not here")
}

func main() {
    qml.Init(nil)
    engine := qml.NewEngine()
    engine.Context().SetVar("crash", &tt{})
    component, err := engine.Load("test.qml", bytes.NewReader([]byte(`
import QtQuick 2.0

Item {
    Component.onCompleted: crash.test()
}
`)))
    if err != nil {
        log.Fatalln(err)
    }

    component.Create(nil)

}

I get this output:

2013/12/26 15:07:38 here
fatal error: runtime: stack split during syscall

runtime stack:
runtime.throw(0x4299eac)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/panic.c:462 +0x69
runtime.newstack()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/stack.c:261 +0x6cb
runtime.morestack()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/asm_amd64.s:225 +0x61

goroutine 4 [stack split]:
syscall.Syscall6(0x7, 0xf68, 0xc2100001b0, 0x0, 0xc21005f360, ...)
    /Users/quarnster/code/3rdparty/go/src/pkg/syscall/asm_darwin_amd64.s:41 +0x5 fp=0x5ffc078
syscall.wait4(0xf68, 0xc2100001b0, 0x0, 0xc21005f360, 0x40450a2, ...)
    /Users/quarnster/code/3rdparty/go/src/pkg/syscall/zsyscall_darwin_amd64.go:32 +0x7d fp=0x5ffc0d8
syscall.Wait4(0xf68, 0x5ffc15c, 0x0, 0xc21005f360, 0xc21000a260, ...)
    /Users/quarnster/code/3rdparty/go/src/pkg/syscall/syscall_bsd.go:126 +0x6e fp=0x5ffc120
os.(*Process).wait(0xc21000a520, 0x0, 0x0, 0x0)
    /Users/quarnster/code/3rdparty/go/src/pkg/os/exec_unix.go:22 +0x10e fp=0x5ffc1b0
os.(*Process).Wait(0xc21000a520, 0x0, 0x0, 0x18)
    /Users/quarnster/code/3rdparty/go/src/pkg/os/doc.go:43 +0x27 fp=0x5ffc1d8
os/exec.(*Cmd).Wait(0xc210065140, 0x0, 0x0)
    /Users/quarnster/code/3rdparty/go/src/pkg/os/exec/exec.go:311 +0x1d9 fp=0x5ffc278
os/exec.(*Cmd).Run(0xc210065140, 0x4113220, 0x42a6e68)
    /Users/quarnster/code/3rdparty/go/src/pkg/os/exec/exec.go:233 +0x54 fp=0x5ffc298
os/exec.(*Cmd).CombinedOutput(0xc210065140, 0x4, 0x5ffc370, 0x1, 0x1, ...)
    /Users/quarnster/code/3rdparty/go/src/pkg/os/exec/exec.go:355 +0x279 fp=0x5ffc328
main.(*tt).Test(0x42a7080)
    /private/tmp/test.go:14 +0x19b fp=0x5ffc440
runtime.call16(0x4114070, 0xc2100000e8)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/asm_amd64.s:338 +0x32 fp=0x5ffc458
reflect.Value.call(0x4113fe0, 0x42a7080, 0x0, 0x138, 0x4138320, ...)
    /Users/quarnster/code/3rdparty/go/src/pkg/reflect/value.go:614 +0x148c fp=0x5ffc990
reflect.Value.Call(0x4113fe0, 0x42a7080, 0x0, 0x138, 0xc210065000, ...)
    /Users/quarnster/code/3rdparty/go/src/pkg/reflect/value.go:451 +0xa5 fp=0x5ffc9f8
github.com/niemeyer/qml.hookGoValueCallMethod(0x6050f40, 0xc210046040, 0x7fff00000000, 0x7fff5fbfc7f0)
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/bridge.go:439 +0x460 fp=0x5ffcc98
----- stack segment boundary -----
runtime.cgocallbackg1()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/cgocall.c:296 +0xbf fp=0x5ffcd70
runtime.cgocallbackg()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/cgocall.c:266 +0x84 fp=0x5ffcd80
runtime.cgocallback_gofunc(0x402a5b3, 0x4001f00, 0x5ffcdf8)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/asm_amd64.s:711 +0x67 fp=0x5ffcd90
runtime.asmcgocall(0x4001f00, 0x5ffcdf8)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/asm_amd64.s:618 +0x2d fp=0x5ffcd98
runtime.cgocall(0x4001f00, 0x5ffcdf8)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/cgocall.c:149 +0x133 fp=0x5ffcde0
github.com/niemeyer/qml._Cfunc_componentCreate(0x612dfc0, 0x0, 0x5ffce38)
    /var/folders/n1/yjqlqd2s04x7th1152h48hsr0000gn/T/go-build434387843/github.com/niemeyer/qml/_obj/_cgo_defun.c:91 +0x31 fp=0x5ffcdf8
github.com/niemeyer/qml.func·022()
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/qml.go:614 +0x57 fp=0x5ffce20
github.com/niemeyer/qml.hookIdleTimer()
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/bridge.go:167 +0x5b fp=0x5ffce50
----- stack segment boundary -----
runtime.cgocallbackg1()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/cgocall.c:296 +0xbf fp=0x5ffcf08
runtime.cgocallbackg()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/cgocall.c:266 +0x84 fp=0x5ffcf18
runtime.cgocallback_gofunc(0x402a5b3, 0x4001d90, 0x5ffcf90)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/asm_amd64.s:711 +0x67 fp=0x5ffcf28
runtime.asmcgocall(0x4001d90, 0x5ffcf90)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/asm_amd64.s:618 +0x2d fp=0x5ffcf30
runtime.cgocall(0x4001d90, 0x5ffcf90)
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/cgocall.c:149 +0x133 fp=0x5ffcf78
github.com/niemeyer/qml._Cfunc_applicationExec(0x42af320)
    /var/folders/n1/yjqlqd2s04x7th1152h48hsr0000gn/T/go-build434387843/github.com/niemeyer/qml/_obj/_cgo_defun.c:73 +0x31 fp=0x5ffcf90
github.com/niemeyer/qml.guiLoop()
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/bridge.go:38 +0x5b fp=0x5ffcfa0
runtime.goexit()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/proc.c:1394 fp=0x5ffcfa8
created by github.com/niemeyer/qml.Init
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/qml.go:58 +0xac

goroutine 1 [chan receive]:
github.com/niemeyer/qml.gui(0xc21000a140)
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/bridge.go:66 +0xa3
github.com/niemeyer/qml.(*Common).Create(0xc210044300, 0x0, 0x1a, 0x6411190)
    /Users/quarnster/code/go/src/github.com/niemeyer/qml/qml.go:615 +0x123
main.main()
    /private/tmp/test.go:33 +0x2e0

goroutine 3 [syscall]:
runtime.goexit()
    /Users/quarnster/code/3rdparty/go/src/pkg/runtime/proc.c:1394
exit status 2

Any ideas?

$ go version
go version devel +176779a4ebed Tue Dec 24 08:24:32 2013 -0800 darwin/amd64
@quarnster
Copy link
Contributor Author

FWIW using C.system instead of the go equivalent works as a work around

@niemeyer
Copy link
Contributor

Please note that these calls are not coming from the qml package. The qml package is just calling back onto the test code at:

main.(*tt).Test(0x42a7080)
    /private/tmp/test.go:14 +0x19b fp=0x5ffc440

Everything above it is not logic from qml.

It also looks like a problem in the Go runtime. I'll report this upstream.

@niemeyer
Copy link
Contributor

Reported at http://golang.org/issue/7227

@niemeyer
Copy link
Contributor

Are you still able to reproduce this issue? If so, can you please run it with GOTRACEBACK=2 and report back on http://golang.org/issue/7227?

Thanks!

@xlab
Copy link

xlab commented May 23, 2014

Accidentally stepped on that rake too. My setup is OS X 10.9.3, Qt 5.3.0, Go — tested with both 1.3beta1 and 1.3beta2. The minimal reproducible code is

package main

import (
    "log"
    "os/exec"
    "gopkg.in/qml.v0"
)

func main() {
    qml.Init(nil)
    out, _ := exec.Command("date").Output() // [1]
    log.Println(string(out))
    engine := qml.NewEngine() // [2]
    log.Println("Hello?")
    _ = engine
}

Program hangs if [1] is getting called after qml.Init(nil) and if any of the go-qml's machinery was used after, like [2]. When hanged, 50% of CPU is used. In this particular case the program reacts on SIGABRT, but in my project, if a complex combination of go routines and for-select is used, this exec call just hangs my program and even the ^C is ignored.So I just kill -9.

I've visited http://golang.org/issue/7227, but seems that there is no any solution yet. 😢

@quarnster
Copy link
Contributor Author

There's a workaround via monkeypatching sigaction et. al. tough

@niemeyer
Copy link
Contributor

@quarnster Are you using that in an app? Maybe we should just do something similar in the qml package itself, to fix the SIGCHILD situation in Mac OS. There's already some memory fiddling to enable testing (see testing.go), but I was not so unhappy about these given it was only for testing. That said, if there's no way to have SIGCHILD working at all otherwise, maybe we should also do that in general for these functions.

@niemeyer niemeyer reopened this Sep 10, 2014
@niemeyer niemeyer changed the title fatal error: runtime: stack split during syscall SIGCHILD handling in Mac OS Sep 10, 2014
@quarnster
Copy link
Contributor Author

I am using it in various apps that appear to be more stable with such a work around in place. However it isn't a catch all solution as applications can still try and override the signal handlers by using the syscall directly. It is nonetheless a viable workaround that I'm presuming would catch most issues.

Reminder per this and this comment, it's enough to simply reset the signal handler trampoline on OSX for the issue to appear even if the signal handler itself isn't touched. This impacts any signal that any lib might try and install even if it's then trying to be "good" and chain the handlers as the standard library doesn't expose the ability to set the trampoline resulting in it getting overwritten when not using the syscall directly.

While Linux allows signal handlers to be chained, the right flags must be used when installing the new handler, so it's still a potential issue on Linux.

The actual code used is in hack.go and utils.c. cinit is used because doing for example &C.signal returns an address to a CGO wrapper function rather than the actual libc function we want to patch.

I don't know of any issues caused by applying the monkey patching.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants