X因为应用程序挂起(使用C ++,Qt,OpenGL)

我的应用程序从networking获取数据并在场景中绘制(场景使用手工制作的OpenGL引擎)。

它工作几个小时。 当我不使用我的桌面时,由于显示器电源pipe理器信号(dpms),我的显示器closures。 然后,当我触摸鼠标或键盘时,显示器打开,应用程序挂起(X也挂起)。

如果我做了xset -dmps操作系统不使用dpms,并且应用程序工作稳定。

这些问题发生在Centos 6和Archlinux中,但是当我在Ubuntu 12.10下运行应用程序时,它工作的很好!

我尝试了不同的NVidia驱动程序。 没有效果。

我试图用SSH来远程login,并使用gdb连接到进程。 监视器打开后,我无法在进程表中find应用程序。

如何诊断问题? 显示器closures/打开时会发生什么(在OpengGL环境中)? 使用dpms时,Ubuntu会做些特别的事吗?

我们猜测问题的原因! 当显示器closures时,我们失去了OpenGL上下文。 监视器唤醒时,应用程序挂起(无上下文)。 由于不同的显示器连接,视操作系统而异的行为:Kubuntu显示器连接VGA电缆。 所以(可能)它对X行为没有影响。

您可以先查看X的日志,通常位于/ var / log /和〜/ .xsession-errors。 这不是没有问题,OpenGL是做一些棘手的事情,所以如果你的应用程序有任何日志打开它。 通过运行ulimit -c unlimited启用核心转储。 您可以通过在gdb中打开它来分析转储,如下所示:

 gdb <executable file> <core dump file> 

看看是否有用,然后研究什么。

您是否尝试过使用GL_ARB_robustness向OpenGL实现添加健壮性支持?

2.6“graphics重置恢复”

某些事件可能会导致GL上下文重置。 这种重置会导致所有的上下文状态丢失。 从这些事件中恢复需要重新创build受影响的上下文中的所有对象。 graphics重置状态的当前状态由返回

 enum GetGraphicsResetStatusARB(); 

返回的符号常量指示自上次调用GetGraphicsResetStatusARB以来GL上下文是否处于复位状态。 NO_ERROR表示GL上下文自上次调用以来未处于复位状态。 GUILTY_CONTEXT_RESET_ARB指示已经检测到归因于当前GL上下文的重置。 INNOCENT_CONTEXT_RESET_ARB表示检测到不能归因于当前GL上下文的重置。 UNKNOWN_CONTEXT_RESET_ARB指示原因未知的检测到的graphics重置。

此外,确保在初始化上下文时有一个debugging上下文,并使用ARB_debug_output扩展来接收日志输出。

 void DebugMessageControlARB(enum source, enum type, enum severity, sizei count, const uint* ids, boolean enabled); void DebugMessageInsertARB(enum source, enum type, uint id, enum severity, sizei length, const char* buf); void DebugMessageCallbackARB(DEBUGPROCARB callback, const void* userParam); uint GetDebugMessageLogARB(uint count, sizei bufSize, enum* sources, enum* types, uint* ids, enum* severities, sizei* lengths, char* messageLog); void GetPointerv(enum pname, void** params); 

例如:

 // Initialize GL_ARB_debug_output ASAP if (glfwExtensionSupported("GL_ARB_debug_output")) { typedef void APIENTRY (*glDebugMessageCallbackARBFunc) (GLDEBUGPROCARB callback, const void* userParam); typedef void APIENTRY (*glDebugMessageControlARBFunc) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, GLboolean enabled); auto glDebugMessageCallbackARB = (glDebugMessageCallbackARBFunc) glfwGetProcAddress("glDebugMessageCallbackARB"); auto glDebugMessageControlARB = (glDebugMessageControlARBFunc) glfwGetProcAddress("glDebugMessageControlARB"); glDebugMessageCallbackARB(debugCallback, this); glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, nullptr, GL_TRUE); } 

 std::string GlfwThread::severityString(GLenum severity) { switch (severity) { case GL_DEBUG_SEVERITY_LOW_ARB: return "LOW"; case GL_DEBUG_SEVERITY_MEDIUM_ARB: return "MEDIUM"; case GL_DEBUG_SEVERITY_HIGH_ARB: return "HIGH"; default: return "??"; } } std::string GlfwThread::sourceString(GLenum source) { switch (source) { case GL_DEBUG_SOURCE_API_ARB: return "API"; case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "SYSTEM"; case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "SHADER_COMPILER"; case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "THIRD_PARTY"; case GL_DEBUG_SOURCE_APPLICATION_ARB: return "APPLICATION"; case GL_DEBUG_SOURCE_OTHER_ARB: return "OTHER"; default: return "???"; } } std::string GlfwThread::typeString(GLenum type) { switch (type) { case GL_DEBUG_TYPE_ERROR_ARB: return "ERROR"; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "DEPRECATED_BEHAVIOR"; case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "UNDEFINED_BEHAVIOR"; case GL_DEBUG_TYPE_PORTABILITY_ARB: return "PORTABILITY"; case GL_DEBUG_TYPE_PERFORMANCE_ARB: return "PERFORMANCE"; case GL_DEBUG_TYPE_OTHER_ARB: return "OTHER"; default: return "???"; } } // Note: this is static, it is called from OpenGL void GlfwThread::debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei, const GLchar *message, const GLvoid *) { std::cout << "source=" << sourceString(source) << " type=" << typeString(type) << " id=" << id << " severity=" << severityString(severity) << " message=" << message << std::endl; AssertBreak(type != GL_DEBUG_TYPE_ERROR_ARB); } 

几乎可以肯定的是,这些扩展在一个体面的OpenGL实现上都可用。 他们帮助很多 。 debugging上下文对所有内容进行validation并向日志投诉。 他们甚至在一些OpenGL实现中的日志输出中给出性能build议。 使用ARB_debug_output可以检查glGetError过时 – 每次调用都会检查你。