2010-09-30 5 views
6

Non riesco a chiamare una funzione di clutter da un thread aggiuntivo. Uso boost :: thread per la filettatura e la libreria di clutter 1.0.C++ - Clutter 1.0 - la funzione di chiamata dal thread causa segfault

Per essere specifici, il thread contiene una funzione in loop che emette il segnale boost :: signals2 :: con i parametri delle coordinate xey di tanto in tanto. Tale segnale è collegato ad una funzione che mani tali variabili ingombrare, cioè x, y in

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

Ed è qui che ottengo un segfault.

Apparentemente il disordine ha alcune routine di gestione dei thread. Ho provato a chiamare

g_thread_init (NULL);

clutter_threads_init();

prima di avviare clutter_main(). Ho anche provato a racchiudere la funzione di clutter in

clutter_threads_enter();

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

clutter_threads_leave();

ma questo non significa anche fare il trucco ..

Ogni suggerimento è apprezzato, grazie in anticipo!

Addendum

Ho appena forgiato un campione minimo di quello che sto cercando di fare. Ho già "protetto" la routine clutter_main() come suggerito. Alcune funzioni di ingombro sembrano funzionare (ad esempio, impostare il colore dello stage o impostare la posizione dell'attore) dal thread separato. C'è ancora qualcosa di sbagliato nel mio codice?

#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 il tuo codice per usare pthread invece di boost :: thread dato che non stai usando alcuna magia Boost e la maggior parte delle persone qui non la ha installata. – karlphillip

risposta

0

ho giocato con il tuo codice e sembra che si sta facendo tutto ok, anche se io non sono esperto in disordine. Inoltre ho fatto funzionare il vostro programma sotto gdb e alcune cose interessanti sono presentato:

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 

A quanto pare l'incidente è accaduto sulla glDisable() from /usr/lib/nvidia-current/libGL.so.1. Si noti che utilizzo il driver OpenGL di NVIDIA sulla mia GeForce 8600 GT.

Puoi confermare che la tua applicazione si blocca anche su computer con altre schede video (non NVIDIA)? Dubito che l'incidente sia dovuto a un bug nell'implementazione OpenGL di NVIDIA.

Per me sembra che * clutter_threads_enter/congedo() * non protegge * clutter_stage_get_actor_at_pos() * da quando ho provato * receive_loop() * essere chiamato come un callback:

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

quindi sappiamo che il vostro codice sembra essere ok.

vi incoraggio a inviare una domanda agli Clutter discussion and help mailing list: disordine-app-devel-list

una mailing list per gli sviluppatori di applicazioni che utilizzano il disordine, le sue librerie di integrazione o toolkit basati su Clutter.

+0

Purtroppo questo non ha risolto il mio problema. Vedi il mio addendum alla mia domanda. Grazie per il tuo suggerimento! –

+0

@ verb-sap Risposta aggiornata. – karlphillip

0

Ho lottato con una situazione molto simile nelle associazioni Python per il disordine. Non sono mai stato in grado di rendere il supporto filo Clutter funziona nel modo che volevo.

Infine, il trucco consisteva nell'usare un processo inattivo (gobject.idle_add in python) per spingere il lavoro che avevo bisogno nel thread principale di clutter. In questo modo ho solo 1 Discussione effettuare chiamate disordine e tutto va bene.

6

Beh, penso di aver trovato la risposta ..

Clutter Docs Gerneral

Si dice nella sezione "modello di threading":

L'unico modo sicuro e portatile da usare il disordine API in un ambiente multi-thread è mai accedere alla API da un filo che non chiamare clutter_init() e clutter_main().

Il modello comune per l'utilizzo di fili con disordine è di utilizzare thread di lavoro per eseguire le operazioni di blocco e quindi installare fonti folli o timeour con il risultato quando il filo finito.

ammasso fornisce varianti thread-consapevole di g_idle_add() e g_timeout_add() che acquisiscono la serratura ammasso prima di richiamare il callback disponibile: clutter_threads_add_idle() e clutter_threads_add_timeout().

Quindi la mia correzione al codice di esempio minimale potrebbe essere quella di modificare il receive_loop() per

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

e di aggiungere la funzione get_actor (come nel codice di esempio nella pagina 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 si prende cura di frenafiletti ecc ..

+0

Ha risolto il tuo problema? – karlphillip

+0

@karlphillip sì funziona ora –

+0

Sì, questa è la risposta giusta. (Ho usato Clutter per alcuni anni nei programmi con thread.) –

0

È possibile utilizzare clutter_threads_add_idle t o aggiornare ClutterActor o è necessario fissare la clutter_threads_enter/leave per cambiare contesto OpenGL pure in modo che si può utilizzare all'interno di un thread.

L'incidente

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 

è perché il thread chiamante non ha acquistato contesto OpenGL così si è schiantato.