Witam. Piszę dość dużą aplikację graficzną.

Zacząłem przerabiać kod odpowiedzialny za wyświetlanie grafiki na GtkDrawingArea.
Działa to tak: chodzi sobie wątek, którego klasa kolejkuje żądania typu: "odśwież cały schemat", "przerysuj pewien obszar", "zmień schemat" itp. Wątek co x ms przetwarza te żądania, rozdziela je na pomniejsze zadania i po prostu wykonuje. Oczywiście mutexy, blokady itp. wszystko zapewnione.

Problem pojawia się, gdy w kolejce zadań pojawi się komenda "przerysuj cały schemat". Na razie oznacza to wykonanie 2 pomniejszych komend: "wypełnij kwadrat kolorem tła zdefiniowanego w opcjach aplikacji" i "narysuj obrazek na pixmapie". Obrazek jest przekazanym wskaźnikiem na GdkPixbuf.

Gdy odpalam aplikację z konsoli, zachowuje się ona tak:

  • 10% - działa poprawnie
  • 50% - zawiesza się mój wątek i wątek gtk podczas wykonywania funkcji gdk_draw_pixbuf()
  • 40% - wywala mi się aplikacja z informacją:
    program: Fatal IO error 11 (Zasoby chwilowo niedostępne) on X server :0.0.
    czasami:
program: ../../src/xcb_io.c:183: process_responses: Warunek zapewnienia `!(req && current_request && !(((long) (req->sequence) - (long) (current_request)) <= 0))' nie został spełniony.
Przerwane

raz tak:

The program 'program' received an X Window System error.
This probably reflects a bug in the program.
The error was 'RenderBadPicture (invalid Picture parameter)'.
  (Details: serial 17355 error_code 171 request_code 149 minor_code 7)
  (Note to programmers: normally, X errors are reported asynchronously;
   that is, you will receive the error a while after causing it.
   To debug your program, run it with the --sync command line
   option to change this behavior. You can then get a meaningful
   backtrace from your debugger if you break on the gdk_x_error() function.)

Gdy odpalam z debuggera: wywala mi się zwykle właśnie na funkcji gdk_draw_pixbuf. zrzut stosu wygląda tak:

Thread [3] 8948 (Suspended : Signal : SIGABRT:Aborted)   
   __kernel_vsyscall() at 0xb7fe2430   
   *__GI_raise() at raise.c:64 0xb6c9a651   
   *__GI_abort() at abort.c:92 0xb6c9da82   
   *__GI___assert_fail() at assert.c:81 0xb6c93718   
   0xb6b54a63   
   _XReply() at 0xb6b54fb6   
   XSync() at 0xb6b48847   
   gdk_flush() at 0xb7bac428   
   0xb7b7a005   
   0xb7b7a321   
   0xb7baa3af   
   gdk_draw_pixbuf() at 0xb7b73b1f   
   gdk_draw_pixbuf() at 0xb7b73b1f   
   SchemeDrawPixbuf::make() at SchematDrawerCommands.cpp:426 0x8142f2a   
   SchematDrawer::Make() at SchematDrawer.cpp:199 0x814014f   
   SchematDrawer::Work() at SchematDrawer.cpp:75 0x813ff1a   
   functionOfPosixThreadMain() at posix_thread.cpp:65 0x813f6bd   
   functionOfPosixThread() at posix_thread.cpp:75 0x813f70c   
   start_thread() at pthread_create.c:300 0xb772896e   
   clone() at clone.S:130 0xb6d3da4e   

Funkcja, w której wszystko się dzieje wygląda tak:

void SchemeDrawPixbuf::make()
{
   rrout<<"void SchemeDrawPixbuf::make()\tBEGIN\n" ;
   SchematDrawer *schemeDrawer = SchematDrawer::Instance() ;

   int x0 = (schemeDrawer->tempSchemeValues.drawingAreaWidth-width)/2 ;
   int y0 = (schemeDrawer->tempSchemeValues.drawingAreaHeight-height)/2 ;

   rrout<<"da_width="<<schemeDrawer->tempSchemeValues.drawingAreaWidth<<
         ", width="<<width<<", x0="<<x0<<"\n" ;
   rrout<<"da_height="<<schemeDrawer->tempSchemeValues.drawingAreaHeight<<
         ", height="<<height<<", y0="<<y0<<"\n" ;

   GdkGC * gc = schemeDrawer->tempSchemeValues.drawingArea->
         style->bg_gc[GTK_WIDGET_STATE(schemeDrawer->tempSchemeValues.drawingArea)] ;

   rrout<<"gc="<<gc<<"\n" ;
   rrout<<"pixbuf="<<pixbuf<<", "<<
         gdk_pixbuf_get_width(pixbuf)<<"x"<<gdk_pixbuf_get_height(pixbuf)<<"\n" ;

   int ww,hh;
   gdk_drawable_get_size(schemeDrawer->tempSchemeValues.pixmapMain, &ww, &hh) ;
   rrout<<"pixmap main: "<<schemeDrawer->tempSchemeValues.pixmapMain<<", "<<ww<<"x"<<hh<<"\n" ;
   gdk_drawable_get_size(schemeDrawer->tempSchemeValues.pixmapBackground, &ww, &hh) ;
   rrout<<"pixmap back: "<<schemeDrawer->tempSchemeValues.pixmapBackground<<", "<<ww<<"x"<<hh<<"\n" ;

    gdk_draw_pixbuf (schemeDrawer->tempSchemeValues.pixmapMain, gc,
            pixbuf, 0, 0, x0, y0, width, height, GDK_RGB_DITHER_NONE, 0, 0);
    rrout<<"narysowano na main\n" ;
    gdk_draw_pixbuf (schemeDrawer->tempSchemeValues.pixmapBackground, gc,
            pixbuf, 0, 0, x0, y0, width, height, GDK_RGB_DITHER_NONE, 0, 0);
    rrout<<"narysowano na back\n" ;
   rrout<<"void SchemeDrawPixbuf::make()\tEND\n" ;
}

wszelkie sugestie mile widziane