X зависает из-за приложения (используйте С++, Qt, OpenGL)

Мое приложение получает данные из сети и рисует их на сцене (сцена использует ручной движок OpenGL).

Он работает в течение нескольких часов. Когда я не использую свой рабочий стол, мой монитор, из-за того, что Display Power Manager Signaling (dpms) отключается. И затем, когда я касаюсь мыши или клавиатуры, монитор включается, и приложение зависает (X тоже зависает).

Если я это сделаю xset -dmps операционная система не использует dpms, и приложение работает стабильно.

Эти проблемы возникают в Centos 6 и Archlinux, но когда я запускаю приложение под Ubuntu 12.10, он отлично работает!

Я пробовал разные драйверы NVidia. Без эффекта.

Я попытался использовать ssh для удаленного входа и подключиться к процессу с помощью gdb. После включения монитора я не могу найти приложение в таблице процессов.

Как диагностировать проблему? Что происходит (в среде OpengGL), когда монитор выключается/включается? Ubuntu делает что-то особенное при использовании dpms?

У нас есть предположение по причинам! Когда монитор выключен, мы теряем контекст OpenGL. Когда монитор просыпается, приложение зависает (нет контекста). И разница в поведении в зависимости от операционной системы связана с различными подключениями монитора: Монитор для Kubuntu подключен к VGA-кабелю. И поэтому (возможно) это не влияет на поведение X.

40
22 нояб. '13 в 14:53
источник поделиться
2 ответов

Вы пытались добавить поддержку устойчивости своей реализации OpenGL, используя GL_ARB_robustness?

2.6 "Графика Reset Восстановление"

Некоторые события могут привести к Reset контекста GL. Такой resetприводит к потере всех состояний контекста. Восстановление от таких событий требует восстановления всех объектов в затронутом контексте. текущее состояние графического состояния Reset возвращается

enum GetGraphicsResetStatusARB();

Возвращаемая символьная константа указывает, был ли контекст GL a Reset в любой точке с момента последнего вызова GetGraphicsResetStatusARB. NO_ERROR указывает, что контекст GL имеет не был в состоянии Reset со времени последнего вызова. GUILTY_CONTEXT_RESET_ARB указывает, что обнаружен Reset, который объясняется текущим контекстом GL. INNOCENT_CONTEXT_RESET_ARB указывает, что обнаружен Reset, который не относится к текущий контекст GL. UNKNOWN_CONTEXT_RESET_ARB указывает обнаруженный графика Reset причина которого неизвестна.

Кроме того, убедитесь, что у вас есть контекст отладки при инициализации вашего контекста и используйте расширение 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. Они помогают, много. Контексты отладки проверяют все и записывают в журнал. Они даже дают рекомендации по производительности в выходе журнала в некоторых реализациях OpenGL. Использование ARB_debug_output делает проверку glGetError устаревшей - она ​​проверяет для вас каждый вызов.

1
07 нояб. '15 в 7:59
источник

Вы можете начать с просмотра журналов X, обычно расположенных /var/log/, и ~/.xsession-errors. Не исключено, что OpenGL делает что-то нехорошее, поэтому, если ваше приложение имеет какой-либо журнал, включите его. Включите дампы ядра, запустив ulimit -c unlimited. Вы можете проанализировать дамп, открыв его в gdb следующим образом:

gdb <executable file> <core dump file>

Посмотрите, если это принесет что-нибудь полезное, тогда исследуйте все, что есть.

1
27 окт. '15 в 21:14
источник

Посмотрите другие вопросы по меткам или Задайте вопрос