C ++ - Clutter 1.0 - 从线程调用函数会导致段错误

时间:2010-09-30 14:51:40

标签: c++ multithreading boost signals clutter

我正在努力从一个额外的线程调用一个杂乱的函数。 我使用boost :: thread进行线程化和clutter库1.0。

具体来说,该线程包含一个循环函数,该函数每隔一段时间发出一个带有x和y坐标参数的boost :: signals2 :: signal。 该信号连接到一个函数,该函数将这些变量置于混乱状态,即

中的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);

     

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 个答案:

答案 0 :(得分:6)

好吧,我想我找到了 答案..

Clutter Docs Gerneral

在“线程模型”部分中说:

  

在多线程环境中使用Clutter API的唯一安全且可移植的方法是永远不要从没有调用clutter_init()和clutter_main()的线程访问API。

     

在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函数(如在menitioned doc页面上的示例代码中所示)

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负责线程锁定等。

答案 1 :(得分:0)

我玩了你的代码,看起来你做的一切都还好,虽然我不是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。请注意,我在GeForce 8600 GT上使用了NVIDIA的OpenGL驱动程序。

您能否确认您的应用程序在其他视频卡(非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 discussion and help邮件列表: clutter-app-devel-list

  

使用Clutter的应用程序开发人员的邮件列表,其集成库或基于Clutter的工具包。

答案 2 :(得分:0)

我在Python绑定中遇到了非常类似的混乱情况。我无法以我想要的方式使Clutter线程支持工作。

最后诀窍是使用空闲proc(python中的gobject.idle_add)将我需要完成的工作推送到主要的混乱线程中。这样我只有1个线程进行杂乱调用,一切都很好。

答案 3 :(得分:0)

您可以使用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上下文所以它崩溃了。