From 5c9d35c1861d7d528cd918718c29c4b5da9d53e5 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Mon, 23 Sep 2019 20:26:52 +0100 Subject: [PATCH] ui/app,ui/app/internal/gl: work around golang.org/issue/34474 Apparently, the (*syscall.LazyProc).Call does not keep its arguments alive across calls. Signed-off-by: Elias Naur --- ui/app/egl_windows.go | 12 ++++++++--- ui/app/internal/gl/gl_windows.go | 35 +++++++++++++++++++++++++------- ui/app/os_windows.go | 19 ++++++++++++++++- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/ui/app/egl_windows.go b/ui/app/egl_windows.go index a16def30..6101db14 100644 --- a/ui/app/egl_windows.go +++ b/ui/app/egl_windows.go @@ -61,17 +61,23 @@ func mustLoadDLL(dll *syscall.LazyDLL, name string) { func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) { var cfg _EGLConfig var ncfg _EGLint - r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(&attribs[0])), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg))) + a := &attribs[0] + r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg))) + issue34474KeepAlive(a) return cfg, r != 0 } func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext { - c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(&attribs[0]))) + a := &attribs[0] + c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a))) + issue34474KeepAlive(a) return _EGLContext(c) } func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win _EGLNativeWindowType, attribs []_EGLint) _EGLSurface { - s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(&attribs[0]))) + a := &attribs[0] + s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a))) + issue34474KeepAlive(a) return _EGLSurface(s) } diff --git a/ui/app/internal/gl/gl_windows.go b/ui/app/internal/gl/gl_windows.go index 1ffc556b..d1690c35 100644 --- a/ui/app/internal/gl/gl_windows.go +++ b/ui/app/internal/gl/gl_windows.go @@ -4,6 +4,7 @@ package gl import ( "math" + "runtime" "syscall" "unsafe" @@ -101,7 +102,9 @@ func (f *Functions) BeginQuery(target Enum, query Query) { } func (c *Functions) BindAttribLocation(p Program, a Attrib, name string) { cname := cString(name) - syscall.Syscall(_glBindAttribLocation.Addr(), 3, uintptr(p.V), uintptr(a), uintptr(unsafe.Pointer(&cname[0]))) + c0 := &cname[0] + syscall.Syscall(_glBindAttribLocation.Addr(), 3, uintptr(p.V), uintptr(a), uintptr(unsafe.Pointer(c0))) + issue34474KeepAlive(c) } func (c *Functions) BindBuffer(target Enum, b Buffer) { syscall.Syscall(_glBindBuffer.Addr(), 2, uintptr(target), uintptr(b.V), 0) @@ -125,7 +128,9 @@ func (c *Functions) BufferData(target Enum, src []byte, usage Enum) { if n := len(src); n == 0 { syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), 0, 0, uintptr(usage), 0, 0) } else { - syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), uintptr(n), uintptr(unsafe.Pointer(&src[0])), uintptr(usage), 0, 0) + s0 := &src[0] + syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), uintptr(n), uintptr(unsafe.Pointer(s0)), uintptr(usage), 0, 0) + issue34474KeepAlive(s0) } } func (c *Functions) CheckFramebufferStatus(target Enum) Enum { @@ -287,7 +292,9 @@ func (c *Functions) GetString(pname Enum) string { } func (c *Functions) GetUniformLocation(p Program, name string) Uniform { cname := cString(name) - u, _, _ := syscall.Syscall(_glGetUniformLocation.Addr(), 2, uintptr(p.V), uintptr(unsafe.Pointer(&cname[0])), 0) + c0 := &cname[0] + u, _, _ := syscall.Syscall(_glGetUniformLocation.Addr(), 2, uintptr(p.V), uintptr(unsafe.Pointer(c0)), 0) + issue34474KeepAlive(c) return Uniform{int(u)} } func (c *Functions) InvalidateFramebuffer(target, attachment Enum) { @@ -305,7 +312,9 @@ func (c *Functions) PixelStorei(pname Enum, param int32) { syscall.Syscall(_glPixelStorei.Addr(), 2, uintptr(pname), uintptr(param), 0) } func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) { - syscall.Syscall6(_glReadPixels.Addr(), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(&data[0]))) + d0 := &data[0] + syscall.Syscall6(_glReadPixels.Addr(), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0))) + issue34474KeepAlive(d0) } func (c *Functions) RenderbufferStorage(target, internalformat Enum, width, height int) { syscall.Syscall6(_glRenderbufferStorage.Addr(), 4, uintptr(target), uintptr(internalformat), uintptr(width), uintptr(height), 0, 0) @@ -315,17 +324,23 @@ func (c *Functions) Scissor(x, y, width, height int32) { } func (c *Functions) ShaderSource(s Shader, src string) { var n uintptr = uintptr(len(src)) - syscall.Syscall6(_glShaderSource.Addr(), 4, uintptr(s.V), 1, uintptr(unsafe.Pointer(&src)), uintptr(unsafe.Pointer(&n)), 0, 0) + psrc := &src + syscall.Syscall6(_glShaderSource.Addr(), 4, uintptr(s.V), 1, uintptr(unsafe.Pointer(psrc)), uintptr(unsafe.Pointer(&n)), 0, 0) + issue34474KeepAlive(psrc) } func (c *Functions) TexImage2D(target Enum, level int, internalFormat int, width, height int, format, ty Enum, data []byte) { if len(data) == 0 { syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), 0) } else { - syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(&data[0]))) + d0 := &data[0] + syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0))) + issue34474KeepAlive(d0) } } func (c *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { - syscall.Syscall9(_glTexSubImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(&data[0]))) + d0 := &data[0] + syscall.Syscall9(_glTexSubImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0))) + issue34474KeepAlive(d0) } func (c *Functions) TexParameteri(target, pname Enum, param int) { syscall.Syscall(_glTexParameteri.Addr(), 3, uintptr(target), uintptr(pname), uintptr(param)) @@ -364,3 +379,9 @@ func cString(s string) []byte { copy(b, s) return b } + +// issue34474KeepAlive calls runtime.KeepAlive as a +// workaround for golang.org/issue/34474. +func issue34474KeepAlive(v interface{}) { + runtime.KeepAlive(v) +} diff --git a/ui/app/os_windows.go b/ui/app/os_windows.go index e71e5757..0ad8ba73 100644 --- a/ui/app/os_windows.go +++ b/ui/app/os_windows.go @@ -549,18 +549,21 @@ func getModuleHandle() (syscall.Handle, error) { func adjustWindowRectEx(r *rect, dwStyle uint32, bMenu int, dwExStyle uint32) { _AdjustWindowRectEx.Call(uintptr(unsafe.Pointer(r)), uintptr(dwStyle), uintptr(bMenu), uintptr(dwExStyle)) + issue34474KeepAlive(r) } func callMsgFilter(m *msg, nCode uintptr) bool { r, _, _ := _CallMsgFilter.Call(uintptr(unsafe.Pointer(m)), nCode) + issue34474KeepAlive(m) return r != 0 } func createWindowEx(dwExStyle uint32, lpClassName uint16, lpWindowName string, dwStyle uint32, x, y, w, h int32, hWndParent, hMenu, hInstance syscall.Handle, lpParam uintptr) (syscall.Handle, error) { + wname := syscall.StringToUTF16Ptr(lpWindowName) hwnd, _, err := _CreateWindowEx.Call( uintptr(dwExStyle), uintptr(lpClassName), - uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpWindowName))), + uintptr(unsafe.Pointer(wname)), uintptr(dwStyle), uintptr(x), uintptr(y), uintptr(w), uintptr(h), @@ -568,6 +571,7 @@ func createWindowEx(dwExStyle uint32, lpClassName uint16, lpWindowName string, d uintptr(hMenu), uintptr(hInstance), uintptr(lpParam)) + issue34474KeepAlive(wname) if hwnd == 0 { return 0, fmt.Errorf("CreateWindowEx failed: %v", err) } @@ -585,10 +589,12 @@ func destroyWindow(hwnd syscall.Handle) { func dispatchMessage(m *msg) { _DispatchMessage.Call(uintptr(unsafe.Pointer(m))) + issue34474KeepAlive(m) } func getClientRect(hwnd syscall.Handle, r *rect) { _GetClientRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(r))) + issue34474KeepAlive(r) } func getDC(hwnd syscall.Handle) (syscall.Handle, error) { @@ -614,6 +620,7 @@ func getMessage(m *msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax uint32 uintptr(hwnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax)) + issue34474KeepAlive(m) return int32(r) } @@ -649,6 +656,7 @@ func msgWaitForMultipleObjectsEx(nCount uint32, pHandles uintptr, millis, mask, func peekMessage(m *msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax, wRemoveMsg uint32) bool { r, _, _ := _PeekMessage.Call(uintptr(unsafe.Pointer(m)), uintptr(hwnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), uintptr(wRemoveMsg)) + issue34474KeepAlive(m) return r != 0 } @@ -671,6 +679,7 @@ func releaseCapture() bool { func registerClassEx(cls *wndClassEx) (uint16, error) { a, _, err := _RegisterClassExW.Call(uintptr(unsafe.Pointer(cls))) + issue34474KeepAlive(cls) if a == 0 { return 0, fmt.Errorf("RegisterClassExW failed: %v", err) } @@ -708,6 +717,7 @@ func setTimer(hwnd syscall.Handle, nIDEvent uintptr, uElapse uint32, timerProc u func screenToClient(hwnd syscall.Handle, p *point) { _ScreenToClient.Call(uintptr(hwnd), uintptr(unsafe.Pointer(p))) + issue34474KeepAlive(p) } func showWindow(hwnd syscall.Handle, nCmdShow int32) { @@ -716,6 +726,7 @@ func showWindow(hwnd syscall.Handle, nCmdShow int32) { func translateMessage(m *msg) { _TranslateMessage.Call(uintptr(unsafe.Pointer(m))) + issue34474KeepAlive(m) } func unregisterClass(cls uint16, hInst syscall.Handle) { @@ -725,3 +736,9 @@ func unregisterClass(cls uint16, hInst syscall.Handle) { func updateWindow(hwnd syscall.Handle) { _UpdateWindow.Call(uintptr(hwnd)) } + +// issue34474KeepAlive calls runtime.KeepAlive as a +// workaround for golang.org/issue/34474. +func issue34474KeepAlive(v interface{}) { + runtime.KeepAlive(v) +}