C ++ - Clutter 1.0 - вызов функции из потока вызывает segfault - PullRequest
6 голосов
/ 30 сентября 2010

Я борюсь с вызовом функции беспорядка из дополнительного потока. Я использую Boost :: Thread для многопоточности и библиотеки беспорядка 1.0.

Если быть точным, поток содержит зацикленную функцию, которая испускает boost :: signal2 :: signal с параметрами координат x и y, время от времени. Этот сигнал связан с функцией, которая передает эти переменные в беспорядок, т. Е. X, y в

clutter_stage_get_actor_at_pos (CLUTTER_STAGE (актер), CLUTTER_PICK_ALL, x, y);

И вот где я получаю сегфо.

Очевидно, что в беспорядке есть несколько процедур обработки потоков. Я пытался позвонить

g_thread_init (NULL);

clutter_threads_init ();

перед запуском clutter_main (). Я также попытался включить функцию беспорядка в

* * Clutter_threads_enter тысячи двадцать-одина (); * * тысяча двадцать-две

clutter_stage_get_actor_at_pos (CLUTTER_STAGE (актер), CLUTTER_PICK_ALL, x, y);

* +1025 * clutter_threads_leave ();

но это тоже не помогает ...

Каждый намек приветствуется, заранее спасибо!

Добавление

Я просто подделал минимальный образец того, что я пытаюсь сделать. Я уже «защитил» подпрограмму clutter_main (), как было предложено. Кажется, что некоторые функции беспорядка работают (например, установка цвета сцены или положение актера) из отдельной нити. Что-то не так с моим кодом?

#include <clutter/clutter.h>
#include <boost/thread.hpp>


ClutterActor *stage;
ClutterActor* rect = NULL;


void receive_loop()
{
while(1)
{
    sleep(1);
    clutter_threads_enter();

    ClutterActor* clicked =  clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL,300, 500);

    clutter_threads_leave();
}

}


int main(int argc, char *argv[]) 
{

    clutter_init(&argc, &argv);

g_thread_init(NULL);
clutter_threads_init();


    stage = clutter_stage_get_default();
    clutter_actor_set_size(stage, 800, 600);


rect = clutter_rectangle_new();
clutter_actor_set_size(rect, 256, 128);
clutter_actor_set_position(rect, 300, 500);
clutter_group_add (CLUTTER_GROUP (stage), rect);    


    clutter_actor_show(stage);


boost::thread thread = boost::thread(&receive_loop);


clutter_threads_enter();
    clutter_main();
clutter_threads_leave();

    return 0;
}

Ответы [ 4 ]

6 голосов
/ 18 октября 2010

Ну, я думаю, что нашел ответ ..

Clutter Docs Gerneral

В разделе "Модель потоков" говорится:

Единственный безопасный и переносимый способ использования API Clutter в многопоточной среде - это никогда не получать доступ к API из потока, который не вызывал clutter_init () и clutter_main ().

Обычный шаблон для использования потоков с Clutter - использование рабочих потоков для выполнения операций блокировки, а затем установка незанятых или временных источников с результатом по завершении потока.

Clutter предоставляет g_idle_add () с поддержкой потокови g_timeout_add (), которые получают блокировку Clutter перед вызовом предоставленного обратного вызова: clutter_threads_add_idle () и clutter_threads_add_timeout ().

Таким образом, моя поправка к минимальному образцу кода будет заключаться в изменении receive_loop () в

void receive_loop()
{
while(1)
{
    sleep(1);

    int pos[2];
    pos[0] = 400;
    pos[1] = 200;

    clutter_threads_add_idle_full (G_PRIORITY_HIGH_IDLE,
                             get_actor,
                             &pos,
                             NULL);
}
}

и добавить функцию get_actor (как в примере кода на упомянутой странице документа)

static gboolean
get_actor (gpointer data)
{
    int* pos = (int*) data;
    ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL, pos[0], pos[1]);

    return FALSE;
}

clutter_threads_add_idle_full заботится о блокировке потока и т. д.

0 голосов
/ 05 января 2012

Вы можете использовать clutter_threads_add_idle для обновления ClutterActor или вам нужно исправить clutter_threads_enter/leave для переключения контекста OpenGL, чтобы вы могли использовать его внутри потока.

Авария

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb799db70 (LWP 3023)]
0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
(gdb) thread apply all bt

Thread 2 (Thread 0xb799db70 (LWP 3023)):
#0  0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1 
#1  0x001b3ec3 in cogl_disable_fog () from /usr/lib/libclutter-glx-1.0.so.0
#2  0x0018b00a in ?? () from /usr/lib/libclutter-glx-1.0.so.0
#3  0x0019dc82 in clutter_stage_get_actor_at_pos () from /usr/lib/libclutter-glx-1.0.so.0
#4  0x080498de in receive_loop () at seg.cpp:19

потому что вызывающий поток не получил контекст OpenGL, поэтому он потерпел крах.

0 голосов
/ 03 октября 2010

Я боролся с очень похожей ситуацией в привязках Python для беспорядка.Мне никогда не удавалось заставить работу поддержки потока Clutter работать так, как я хотел.

В конце концов уловка была в том, что я использовал простейший процесс (gobject.idle_add в python), чтобы перенести необходимую работу в основной беспорядокнить.Таким образом, у меня только 1 поток, делающий беспорядочные вызовы, и все в порядке.

0 голосов
/ 30 сентября 2010

Я играл с твоим кодом, и, кажется, ты все делаешь нормально, хотя я не эксперт в Clutter.Я также запустил вашу программу под GDB, и обнаружились некоторые интересные вещи:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb799db70 (LWP 3023)]
0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
(gdb) thread apply all bt

Thread 2 (Thread 0xb799db70 (LWP 3023)):
#0  0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1 
#1  0x001b3ec3 in cogl_disable_fog () from /usr/lib/libclutter-glx-1.0.so.0
#2  0x0018b00a in ?? () from /usr/lib/libclutter-glx-1.0.so.0
#3  0x0019dc82 in clutter_stage_get_actor_at_pos () from /usr/lib/libclutter-glx-1.0.so.0
#4  0x080498de in receive_loop () at seg.cpp:19

Очевидно, сбой произошел на glDisable () from /usr/lib/nvidia-current/libGL.so.1.Обратите внимание, что я использую драйвер NVIDIA OpenGL на моем GeForce 8600 GT.

Можете ли вы подтвердить, что ваше приложение также дает сбой на компьютерах с другими видеокартами (не NVIDIA)?Я сомневаюсь, что сбой произошел из-за ошибки в реализации NVIDIA OpenGL.

Мне кажется, что * clutter_threads_enter / exit () * не защищает * clutter_stage_get_actor_at_pos () *, так как я тестировал * receive_loop () *, вызываемыйв качестве обратного вызова:

g_signal_connect(stage, "button-press-event", G_CALLBACK(receive_loop), NULL);

, поэтому мы знаем, что ваш код, кажется, в порядке.

Я призываю вас отправить свой вопрос в Обсуждение беспорядка и помощь список рассылки: clutter-app-devel-list

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...