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

ver*_*sap 6 c++ multithreading boost signals clutter

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

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

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;
}
Run Code Online (Sandbox Code Playgroud)

ver*_*sap 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);
}
}
Run Code Online (Sandbox Code Playgroud)

并添加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;
}
Run Code Online (Sandbox Code Playgroud)

clutter_threads_add_idle_full负责线程锁等.


kar*_*lip 0

我玩了你的代码,看起来你做的一切都很好,尽管我不是混乱方面的专家。我还在 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
Run Code Online (Sandbox Code Playgroud)

显然,事故发生在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);
Run Code Online (Sandbox Code Playgroud)

所以我们知道您的代码似乎没问题。

我鼓励您将问题发送到Clutter 讨论和帮助邮件列表:clutter-app-devel-list

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