Newsgroup: it.comp.os.linux.development
Titolo: pthread e gtk

Ciao a tutti.
Mi trovo ormai da una settimana fermo su una semplice applicazione.
Sto lavorando su un sistema linux embedded. Il sistema operativo č
derivato da X-LINUX 5.2. Il kernel č stato cambiato al 2.4.24. E' stato
inserito il server X versione 4.3.0, e le librerie gtk2 2.0.6, glic 2.2.4.
Sto sviluppando con gtk un programma che visualizza un'immagine e una
volta ogni x secondi cambia l'immagine con un'altra.
Per fare questo ho creato un thread che non fa altro che aspettare gli x
secondi e accodare la richiesta di cambiare immagine.
Il problema č che all'esecuzione mi esce un errore del tipo:
Applicazione: Fatal IO error 0 (Success) on X server :0.0.
Se invece di visualizzare l'immagine, visualizzo un bottone tutto funziona
a meraviglia.
Anche se non ridimensiono la finestra il tutto funziona...
Allego il codice:
-----------------------------------
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <glib.h>
#include <signal.h>
#include "/usr/include/glib-2.0/glib.h"
GtkWidget *immagine;
GtkWidget *immagine2;
GtkWidget *contenitore;
GtkWidget *frm_main;
gboolean Ciclo(gpointer data)
{
  gtk_widget_queue_draw(immagine);
  return TRUE;
}
void *Cicla(void *data)
{
  while (1)
    {
      gtk_image_set_from_file(GTK_IMAGE(immagine), "/prove/immagine2.bmp");
      g_idle_add(Ciclo, NULL);
      sleep(1);
      gtk_image_set_from_file(GTK_IMAGE(immagine), "/prove/immagine.bmp");
      g_idle_add(Ciclo, NULL);
      sleep(1);
     }
  return NULL;
}
void termina(void)
{
  gtk_main_quit();
}
int main (int argc, char **argv)
{
  pthread_t pt;
 
  gtk_init(&argc, &argv);
  frm_main=gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_decorated(GTK_WINDOW(frm_main), FALSE);
  g_signal_connect(GTK_OBJECT(frm_main), "delete_event",
GTK_SIGNAL_FUNC(termina), NULL);
 
  immagine = gtk_image_new_from_file("/prove/immagine.jpg");
  contenitore=gtk_fixed_new();
 
  gtk_fixed_put(GTK_FIXED(contenitore), immagine, 0, 0);
  gtk_container_add(GTK_CONTAINER(frm_main), contenitore);
  gtk_widget_show(immagine);
  gtk_widget_set_usize(GTK_WIDGET(frm_main), 1024, 768);
  gtk_widget_set_usize(contenitore, 1024, 768);
  gtk_widget_show(contenitore);
  gtk_widget_show(frm_main);
  pthread_create(&pt, NULL, Cicla, NULL);
  gtk_main();
  return 0;
}
------------------------------------------------------
e compilo con il seguente comando
gcc `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0 `
Applicazione.c libpthread.a -o Applicazione
dove libpthread.a č all'interno della direcotry di compilazione.
Ho provato anche ad inserire g_thread_init(NULL) all'inizio con i relativi
gtk_thread_init(), gtk_thread_enter() e gtk_thread_leave e mi va in
Segmentation fault.
Facendo un strace l'errore che mi ritrovo č:
writev(3, [{"\2\2\2\0\2\2\2\0\2\2\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"...,
300}],
1) = -1 EAGAIN (Resource temporarily unavailable)
write(2, "Confessionali: Fatal IO error 0 "..., 60Applicazione: Fatal IO
error
0 (Success) on X server :0.0.
) = 60
write(5, " \20\5\10\2\0\0\0\1\0\0\0P\346\377\277\0p&@\3348\'@2:\0"...,
148) = 148
rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0
rt_sigsuspend([] <unfinished ...>
--- SIGRTMIN (Unknown signal 32) @ 0 (0) ---
<... rt_sigsuspend resumed> )           = -1 EINTR (Interrupted system
call)
sigreturn()                             = ? (mask now [RTMIN])
wait4(231, NULL, __WCLONE, NULL)        = 231
munmap(0x4070a000, 4096)                = 0
exit_group(1)                           = ?
Vi prego qualcuno mi aiuti.....    :(
 
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it



 secondi e accodare la richiesta di cambiare immagine.
Tutte le chiamate a GTK, compresa quindi
 >   gtk_image_set_from_file(GTK_IMAGE(immagine), "/prove/immagine2.bmp");
Devono essere fatte dal thread che gestisce GTK, questo perche' , detto 
in poche parole, altrimenti rischi che due thread modifichino la 
struttura gerarchica della GUI nello stesso momento.
Ci sono delle primitive per sincronizzare piu' thread, ma il modo piu' 
semplice per fare quello che ti serve e' probabilmente quello di 
aggiungere un timeout con gtk_timeout_add e togliere la dipendenza dalle 
pthread, pseudocodice:
cicla
{
	static int switch = 0;
	if (switch)
	gtk_image_set_from_file(GTK_IMAGE(immagine), "/prove/immagine2.bmp");
	else
	gtk_image_set_from_file(GTK_IMAGE(immagine), "/prove/immagine1.bmp");
	switch ^= 1;
}
main
{
[creo gui]
g_timeout_add(cicla, 1000)
gtk_main()
}
Ovvio che se fai qualcosa di molto piu' complicato (tipo calcoli pesanti 
che non devono bloccare l'interfaccia) non puoi evitare l'uso dei 
pthread, ma e' possibile comunque ricondurti in un caso simile 
effettuando l'aggiornamento della GUI tramite una comunicazione tramite 
socket e triggerando il socket con gtk_input_add o simili (su GTK 2 si 
dovrebbero usare i GIO channels che sono analoghi).
Esistono delle funzioni per gestire la sincronizzazione tra i thread in 
GTK, ma ti complichi le cose in modo esagerato.
Guarda qui per una trattazione piu' approfondita:
http://www.gtk.org/api/2.6/gdk/gdk-Threads.html
Bye,
  Gabry