C++ - Clutter 1.0 - вызов функции из потока вызывает segfault

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

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

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

И тут я получаю segfault.

По-видимому, у clutter есть некоторые процедуры обработки потоков. я пытался позвонить

g_thread_init(НОЛЬ);

clutter_threads_init();

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

clutter_threads_enter();

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

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

person verb-sap    schedule 30.09.2010    source источник
comment
Измените свой код, чтобы использовать pthread вместо boost::thread, поскольку вы не используете магию Boost, и у большинства людей она не установлена.   -  person karlphillip    schedule 12.10.2010


Ответы (4)


Что ж, думаю, я нашел ответ..

Главный свод документов по беспорядку

В разделе модель потоковой передачи говорится:

Единственный безопасный и переносимый способ использования Clutter API в многопоточной среде — никогда не обращаться к 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 заботится о блокировке потока и т. д.

person verb-sap    schedule 18.10.2010
comment
Ага, это правильный ответ. (Использую Clutter уже несколько лет в многопоточных программах.) - person Bob Murphy; 11.11.2010

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

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

person Bill Gribble    schedule 03.10.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/leave()* не защищает *clutter_stage_get_actor_at_pos()*, поскольку я тестировал вызов *receive_loop()* как обратный вызов:

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

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

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

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

person karlphillip    schedule 30.09.2010
comment
К сожалению, это не решило мою проблему. Смотрите мое дополнение к моему вопросу. Спасибо за ваше предложение! - person verb-sap; 12.10.2010

Вы можете либо использовать 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, поэтому произошел сбой.

person Hieu Le Trung    schedule 05.01.2012