Go会导致OpenGL随着时间的推移而发生段错误。但不是时间。后来

时间:2014-05-26 04:01:08

标签: linux opengl go glfw cgo

我有以下两个文件:

bridge.go:

package cube

// #cgo LDFLAGS: -lGL -lGLEW -lglfw
// #include <GLFW/glfw3.h>
// int init(GLFWwindow**);
// void render(GLFWwindow*);
import "C"

import (
    "fmt"
    "time"
)

func Init() {
    var window *_Ctype_GLFWwindow
    windowWat := (*[0]byte)(window)
    fmt.Printf("Calling init\n")
    if C.init(&windowWat) != 1 {
        return
    }
    window = (*_Ctype_GLFWwindow)(windowWat)

    //t := time.Tick(time.Second) // Doesn't work
    t := time.After(time.Second) // Works

    <-t
    fmt.Println("Rendering")
    C.render((*[0]byte)(window))

    select {}
}

cube.c:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#define INIT_WINDOW_W (800)
#define INIT_WINDOW_H (800)

void render(GLFWwindow* window) {
    glClearColor(135.0f / 255.0f, 206.0f / 255.0f, 250.f / 254.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glfwSwapBuffers(window);
}

static void glfw_error(int errno, const char* description) {
    fprintf(stderr, "GLFW [%d] %s\n", errno, description);
    exit(1);
}

int init(GLFWwindow** window) {
    GLenum glewErr;

    glfwSetErrorCallback(glfw_error);
    if (!glfwInit()) {
        return 0;
    }

    *window = glfwCreateWindow(
        INIT_WINDOW_H,
        INIT_WINDOW_W,
        "wat",
        NULL,
        NULL
    );
    if (*window == NULL) {
        glfwTerminate();
        return 0;
    }

    glfwMakeContextCurrent(*window);

    glewErr = glewInit();
    if (glewErr != GLEW_OK) {
        fprintf(stderr, "glewInit failed: %s\n", glewGetErrorString(glewErr));
        return 0;
    }

    if (!GL_VERSION_2_0) {
        fprintf(stderr, "Don't have OpenGL >= 2.0\n");
        return 0;
    }

    return 1;
}

除了调用cube.Init()而且没有其他内容的main.go文件。

我的问题在于调用C.render之前的行。如果我做time.After,它可以正常工作,并显示一个蓝色的窗口,因为它应该。如果我执行time.Tick,它很少会显示该蓝色窗口,但显示黑色窗口或段错误。从我的实际代码中可以看出这个测试用例非常简单。

我有一种感觉,那就是调度程序会以某种方式弄乱,但我无法思考如何(或如何测试/修复它)。我很好奇是否有人有任何想法导致这种情况,或者可以想出任何进一步调查的方法。

其他可能重要的信息:

  • Arch linux,3.14.4-1-ARCH.x86_64
  • GLFW 3.0.4-1
  • GLEW 1.10.0-2
  • nVidia GeForce GTX 570M
  • nVidia driver 337.12-1
  • go1.2 linux / amd64

编辑:

这里是段错误消息:

SIGSEGV: segmentation violation
PC=0x7fda7d6a2e29
signal arrived during cgo execution

runtime.cgocall(0x401260, 0x7fda7d6f0e58)
        /opt/go/src/pkg/runtime/cgocall.c:149 +0x11b fp=0x7fda7d6f0e40
game/cube._Cfunc_render(0x24e13b0)
        game/cube/_obj/_cgo_defun.c:62 +0x31 fp=0x7fda7d6f0e58
game/cube.Init()
        /tmp/wat/cube/bridge.go:28 +0x156 fp=0x7fda7d6f0ee0
main.main()
        /tmp/wat/main.go:10 +0xac fp=0x7fda7d6f0f48
runtime.main()
        /opt/go/src/pkg/runtime/proc.c:220 +0x11f fp=0x7fda7d6f0fa0
runtime.goexit()
        /opt/go/src/pkg/runtime/proc.c:1394 fp=0x7fda7d6f0fa8

goroutine 3 [syscall]:
runtime.goexit()
        /opt/go/src/pkg/runtime/proc.c:1394

rax     0x0
rbx     0x24e13b0
rcx     0x7fda7d6f0e58
rdx     0x7fda7d6f0df0
rdi     0x24e13b0
rsi     0xc210001900
rbp     0xc21002a000
rsp     0x7fda76506dc8
r8      0xc210001120
r9      0x7fda7d6f0df0
r10     0x7fda76506ba0
r11     0x7fda7d6a2e20
r12     0x0
r13     0x7fda76507700
r14     0x0
r15     0x7fda76d07c80
rip     0x7fda7d6a2e29
rflags  0x10202
cs      0x33
fs      0x0
gs      0x0
exit status 2

似乎在调用glClearColor

时出现了段错误

1 个答案:

答案 0 :(得分:1)

将我的评论转化为答案:

出于某种原因,OpenGL通常要求所有内容都在同一个OS线程中运行。 time.Tick和time.After调用不同的运行时函数,其中一个可能导致不同的opengl调用在不同的线程中运行。默认情况下,Go make不保证在特定线程上运行goroutine。

要解决此问题,您需要使用runtime.LockOSThread。这将确保goroutine和只有那个goroutine在当前线程上运行。

您可以在此处详细了解该主题:https://groups.google.com/forum/#!topic/golang-nuts/5Pvv1Gr1eoo