Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

X hangs up because of application (use C++, Qt, OpenGL)

My application gets data from the network and draws it on the scene (scene uses handmade OpenGL engine).

It works for several hours. When I'm not using my desktop, my monitor, because of Display Power Manager Signaling (dpms) turns off. And then, when I touch the mouse or keyboard, the monitor turns on, and the application hangs up (X hangs up too).

If I do xset -dmps the operation system doesn't use dpms and the application works stable.

These issues occur in Centos 6 and Archlinux, but when I run the application under Ubuntu 12.10 it works great!

I tried different NVidia drivers. No effect.

I tried to use ssh to remote login and attach to the process with gdb. After monitor is turned on I can't find the application in the process table.

How to diagnose the problem? What happens (in OpengGL environment) when the monitor turns off/turns on? Does Ubuntu do something special when using dpms?

We have a guess for reasons of the problem! When the monitor is turned off we lose the OpenGL context. When the monitor wakes up, the application hangs (no context). And the difference in behavior depending on the operation system is because of different monitor connections: The monitor for Kubuntu is connected with VGA cable. And so (probably) it has no influence on X behaviour.

like image 993
poljak181 Avatar asked Nov 22 '13 11:11

poljak181


2 Answers

Have you tried adding robustness support to your OpenGL implementation using GL_ARB_robustness?

2.6 "Graphics Reset Recovery"

Certain events can result in a reset of the GL context. Such a reset causes all context state to be lost. Recovery from such events requires recreation of all objects in the affected context. The current status of the graphics reset state is returned by

enum GetGraphicsResetStatusARB();

The symbolic constant returned indicates if the GL context has been in a reset state at any point since the last call to GetGraphicsResetStatusARB. NO_ERROR indicates that the GL context has not been in a reset state since the last call. GUILTY_CONTEXT_RESET_ARB indicates that a reset has been detected that is attributable to the current GL context. INNOCENT_CONTEXT_RESET_ARB indicates a reset has been detected that is not attributable to the current GL context. UNKNOWN_CONTEXT_RESET_ARB indicates a detected graphics reset whose cause is unknown.

Also, make sure you have a debug context when you initialize your context, and use the ARB_debug_output extension to receive log 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);

For example:

// 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);
}

You almost certainly have both of those extensions available on a decent OpenGL implementation. They help, a lot. Debug contexts do validation on everything and complain to the log. They even give performance suggestions in the log output in some OpenGL implementations. Using ARB_debug_output makes checking glGetError obsolete - it checks for you every call.

like image 173
doug65536 Avatar answered Oct 23 '22 12:10

doug65536


You can start by looking at the X's logs, usually located /var/log/, and ~/.xsession-errors. It's not out of the question that OpenGL is doing something screwy, so if your app has any logging turn it on. Enable core dumps by running ulimit -c unlimited. You can analyze the dump by opening it in gdb like this:

gdb <executable file> <core dump file>

See if that produces anything useful, then research whatever that is.

like image 38
ventsyv Avatar answered Oct 23 '22 11:10

ventsyv