2010-09-30 13 views
6

Estoy luchando con llamar a una función de desorden de un hilo adicional. Uso boost :: thread para threading y la biblioteca de clutter 1.0.C++ - Clutter 1.0 - la función de llamada desde el hilo causa segfault

Para ser específico, el subproceso contiene una función en bucle que emite boost :: signals2 :: señal con parámetros de coordenadas x e y de vez en cuando. Esa señal se conecta a una función que manos esas variables para el desorden, es decir, x, y en

clutter_stage_get_actor_at_pos (CLUTTER_STAGE (Actor), CLUTTER_PICK_ALL, X, Y);

Y ahí es donde recibo una segfault.

Parece que el desorden tiene algunas rutinas de manejo de hilos. Intenté llamar a

g_thread_init (NULL);

clutter_threads_init();

antes de iniciar clutter_main(). También traté de adjuntar la función de desorden en

clutter_threads_enter();

clutter_stage_get_actor_at_pos (CLUTTER_STAGE (actor), CLUTTER_PICK_ALL, x, y);

clutter_threads_leave();

sino que también no hace el truco ..

Cada pista se aprecia, gracias por adelantado!

Adición

acabo forjaron una muestra mínima de lo que estoy tratando de hacer. Ya 'protegí' la rutina clutter_main() como se sugiere. Algunas funciones de desorden parecen funcionar (por ejemplo, establecer el color de la etapa o establecer la posición del actor) del hilo separado. ¿Todavía hay algo mal con mi código?

#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; 
} 
+0

Cambia el código para usar pthread en lugar de boost :: thread ya que no estás utilizando ninguna magia de Boost y la mayoría de las personas aquí no lo tienen instalado. – karlphillip

Respuesta

0

He jugado con tu código y parece que estás haciendo todo bien, aunque no soy un experto en Clutter. También me encontré con su programa bajo el BGF y algunas cosas interesantes presenté:

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 

Al parecer, el accidente ocurrió en glDisable() from /usr/lib/nvidia-current/libGL.so.1. Tenga en cuenta que utilizo el controlador OpenGL de NVIDIA en mi GeForce 8600 GT.

¿Puede confirmar que su aplicación también se cuelga en las computadoras con otras tarjetas de video (no NVIDIA)? Dudo que el bloqueo se deba a un error en la implementación de OpenGL de NVIDIA.

Para mí, parece que * clutter_threads_enter/licencia() * no está protegiendo * clutter_stage_get_actor_at_pos() * Desde que probé * receive_loop() * ser llamada como llamada de retorno:

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

así que sabemos que su el código parece estar bien.

le animo a enviar su pregunta a la lista de correo Clutter discussion and help: desorden-app-devel-list

una lista de correo para desarrolladores de aplicaciones que utilizan el desorden, sus bibliotecas de integración o kits de herramientas basadas en desorden.

+0

Lamentablemente eso no solucionó mi problema. Ver mi apéndice a mi pregunta. ¡Gracias por tu sugerencia! –

+0

@ verb-sap Respuesta actualizada. – karlphillip

0

Luché con una situación muy similar en los enlaces de Python para el desorden. Nunca fui capaz de hacer que el soporte del hilo Clutter funcionara como yo quería.

Lo que finalmente hizo el truco fue usar un proceso inactivo (gobject.idle_add en python) para insertar el trabajo que necesitaba hecho en el hilo principal del desorden. De esa manera solo tengo 1 hilo haciendo llamadas desordenadas y todo está bien.

6

Bueno, creo que he encontrado la respuesta ..

Clutter Docs Gerneral

Se dice en la sección "enhebrar modelo":

La única manera segura y portátil para utilizar el desorden API en un entorno de subprocesos múltiples es nunca tener acceso a la API desde un subproceso que no llamó a clutter_init() y clutter_main().

El patrón común para usar subprocesos con Clutter es usar subprocesos de trabajo para realizar operaciones de bloqueo y luego instalar fuentes inactivas o timeour con el resultado cuando finaliza el subproceso.

Clutter proporciona variantes de g_idle_add() y g_timeout_add() que adquieren Clutter lock antes de invocar la devolución de llamada proporcionada: clutter_threads_add_idle() y clutter_threads_add_timeout().

Así que mi corrección en el código de muestra mínima sería alterar la receive_loop() para

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

y añadir la función get_actor (como en el ejemplo de código en la página doc menitioned)

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 se encarga de bloqueo de rosca etc ..

+0

¿Resolvió su problema? – karlphillip

+0

@karlphillip sí funciona bien ahora –

+0

Sí, esa es la respuesta correcta. (He estado utilizando Clutter durante algunos años en programas con subprocesos). –

0

puede utilizar clutter_threads_add_idle t o actualice ClutterActor o necesita reparar el clutter_threads_enter/leave para cambiar el contexto de OpenGL también para que pueda usarlo dentro de un hilo.

El accidente

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 

se debe a que el subproceso de llamada no adquirió contexto OpenGL por lo que se estrelló.

Cuestiones relacionadas