在编译成功后RB-SLAM2时,运行建图后,程序意外在结束时出现段错误。即在多线程环境下使用 OpenGL 时,遇到
New map created with 1053 points
Received 'EGL_BAD_ACCESS' trying to set current EGL context.
When calling 'MakeCurrent()' from a different thread, you need to unset the previous context first by calling 'RemoveCurrent()'.
Received 'EGL_BAD_ACCESS' trying to set current EGL context.
错误,通常是由于多个线程同时操作 EGL 上下文(EGLContext)导致的。本文将分析错误的原理,并提供解决方案。
错误原理
1. EGL 上下文 (EGLContext) 是线程绑定的
在 EGL(Embedded-System Graphics Library)中,每个 EGLContext
只能在 单个线程 内被绑定并使用。如果一个线程已经持有 EGL 上下文,而另一个线程尝试使用同一上下文,就会触发 EGL_BAD_ACCESS
错误。
2. 多线程同时访问同一个 OpenGL 上下文
当多个线程尝试 同时调用 OpenGL API 并操作相同的 EGL 上下文,而没有适当的同步机制时,就会出现 EGL_BAD_ACCESS
。
3. 线程未正确解除上下文
错误提示 When calling 'MakeCurrent()' from a different thread, you need to unset the previous context first by calling 'RemoveCurrent()'.
说明问题的关键:
-
如果一个线程已经绑定了
EGLContext
,另一个线程要使用它,必须先调用eglMakeCurrent(NULL, NULL, NULL)
来 解除 之前的绑定。 -
否则,EGL 仍然认为上下文归属于原来的线程,导致
EGL_BAD_ACCESS
。
4. 竞争条件与段错误(核心已转储)
如果多个线程同时访问 OpenGL 资源(如 EGLSurface
或 EGLContext
),并且没有适当的互斥锁或同步机制,就可能导致竞争条件,最终触发 段错误 (core dumped)。
解决方案
临时生效解决方案:
export __GL_SINGLETHREADED=1
或者添加到环境变量,长时间生效。
线程同步
如果必须在多个线程中共享 OpenGL 资源,建议使用 互斥锁 (std::mutex
) 来确保同一时间只有一个线程访问 OpenGL。
std::mutex gl_mutex;
gl_mutex.lock();
// OpenGL 渲染操作
gl_mutex.unlock();
成功运行并正常退出:
总结
多线程操作 OpenGL 时,必须确保:
-
每个线程使用 独立的 EGL 上下文,避免多个线程同时操作同一个上下文。
-
线程切换前,使用
eglMakeCurrent(NULL, NULL, NULL)
解绑 EGLContext。 -
通过
export __GL_SINGLETHREADED=1
禁用多线程 OpenGL,避免竞态条件。 -
必要时使用 互斥锁 保证线程安全。
如果你的应用需要高性能渲染,建议使用 OpenGL 的多线程渲染队列,而不是多个线程直接访问 EGL 上下文。
这样可以避免 EGL_BAD_ACCESS
和段错误,提升 OpenGL 在多线程环境下的稳定性。