Repository: go
Issue: x/exp/shiny/driver/gldriver: deadlock when creating multiple windows on darwin
Labels: NeedsInvestigation

I am attempting to create multiple windows, to avoid having to write any layout or windowing code myself.

``` go
func main() {
    driver.Main(func(s screen.Screen) {
        w, err := s.NewWindow(nil)
        if err != nil {
            log.Fatal(err)
        }
        w2, err := s.NewWindow(nil)
        if err != nil {
            log.Fatal(err)
        }
        _, _ = w, w2
    })
}
```

This hangs at the second call to `NewWindow`. Backtrace:

```
SIGQUIT: quit
PC=0x405bacb m=0
signal arrived during cgo execution

goroutine 1 [chan receive, locked to thread]:
runtime.mach_semaphore_wait(0xc800001003, 0x4228e00, 0x4031592, 0x40e1d00, 0x7fff5fbfd480, 0x4228e00, 0x404fb79, 0xffffffffffffffff, 0x419aba0, 0x7fff5fbfd494, ...)
    $GOROOT/src/runtime/sys_darwin_amd64.s:411 +0xb fp=0x7fff5fbfd428 sp=0x7fff5fbfd420
runtime.semasleep1(0xffffffffffffffff, 0x419aba0)
    $GOROOT/src/runtime/os1_darwin.go:423 +0xdf fp=0x7fff5fbfd460 sp=0x7fff5fbfd428
runtime.semasleep.func1()
    $GOROOT/src/runtime/os1_darwin.go:439 +0x29 fp=0x7fff5fbfd480 sp=0x7fff5fbfd460
runtime.systemstack(0x7fff5fbfd498)
    $GOROOT/src/runtime/asm_amd64.s:307 +0xab fp=0x7fff5fbfd488 sp=0x7fff5fbfd480
runtime.semasleep(0xffffffffffffffff, 0x0)
    $GOROOT/src/runtime/os1_darwin.go:440 +0x36 fp=0x7fff5fbfd4b8 sp=0x7fff5fbfd488
runtime.notesleep(0x4229248)
    $GOROOT/src/runtime/lock_sema.go:166 +0xed fp=0x7fff5fbfd4f0 sp=0x7fff5fbfd4b8
runtime.stoplockedm()
    $GOROOT/src/runtime/proc.go:1682 +0xae fp=0x7fff5fbfd510 sp=0x7fff5fbfd4f0
runtime.schedule()
    $GOROOT/src/runtime/proc.go:2030 +0x6e fp=0x7fff5fbfd548 sp=0x7fff5fbfd510
runtime.park_m(0xc820000180)
    $GOROOT/src/runtime/proc.go:2137 +0x18b fp=0x7fff5fbfd570 sp=0x7fff5fbfd548
runtime.mcall(0x4059e1a)
    $GOROOT/src/runtime/asm_amd64.s:233 +0x5b fp=0x7fff5fbfd580 sp=0x7fff5fbfd570

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
    $GOROOT/src/runtime/asm_amd64.s:1998 +0x1

goroutine 19 [syscall, locked to thread]:
golang.org/x/exp/shiny/driver/gldriver._Cfunc_doNewWindow(0x30000000400, 0x0)
    golang.org/x/exp/shiny/driver/gldriver/_obj/_cgo_gotypes.go:200 +0x42
golang.org/x/exp/shiny/driver/gldriver.newWindow(0x0, 0x413f320, 0x0, 0x0)
    golang.org/x/exp/shiny/driver/gldriver/cocoa.go:62 +0x63
golang.org/x/exp/shiny/driver/gldriver.(*screenImpl).NewWindow(0x4228a40, 0x0, 0x0, 0x0, 0x0, 0x0)
    golang.org/x/exp/shiny/driver/gldriver/screen.go:125 +0x4c
main.main.func1(0x5aab2b8, 0x4228a40)
    main.go:35 +0x14f
golang.org/x/exp/shiny/driver/gldriver.driverStarted.func1()
    golang.org/x/exp/shiny/driver/gldriver/cocoa.go:102 +0x47
created by golang.org/x/exp/shiny/driver/gldriver.driverStarted
    golang.org/x/exp/shiny/driver/gldriver/cocoa.go:104 +0x2b

goroutine 20 [select, locked to thread]:
golang.org/x/exp/shiny/driver/gldriver.drawLoop(0xc820092000, 0x1)
    golang.org/x/exp/shiny/driver/gldriver/cocoa.go:147 +0x482
created by golang.org/x/exp/shiny/driver/gldriver.preparedOpenGL
    golang.org/x/exp/shiny/driver/gldriver/cocoa.go:80 +0x117
```

The interesting goroutine is goroutine 19, which is blocked in the cgo `doNewWindow` call, at `dispatch_sync(dispatch_get_main_queue(), ...`. I've confirmed that at the time of the call, the current thread and the main thread are different. So either (a) the main thread is blocked somewhere else, (b) the main thread's run loop is stopped, or (c) the main thread's run loop is in the wrong mode.

Workaround suggestions would be very welcome, no matter how hacky.

/cc @nigeltao @crawshaw