GdkWindowQueueItem::serial variable overflow in caused segv in expose event



Hi all,

I have posted a message regarding "segv in expose event" early this year,
http://mail.gnome.org/archives/gtk-devel-list/2007-March/msg00086.html

some people suggested we upgrade to the latest gtk library to see whether the problem still remained or not. I found that this issue still existed. Further investigation has been performed and something interesting showed up. I found that in function _gdk_window_process_expose, the serial variable in GdkWindowQueueItem structure just overflowed, so that it became less than xevent.serial, so the item would be removed from the queue, which SHOULD NOT happen.

Here is the proof:
(gdb) bt
#0  0xb794ba9a in g_object_remove_weak_pointer (object=0x9a35d88, weak_pointer_location=0x9a35a88
)
    at gobject.c:1548
#1  0xb7a2bd61 in queue_item_free (item=0x9a35a88) at gdkgeometry-x11.c:914
#2  0xb7a2c0a5 in _gdk_window_process_expose (window=0x9a38f18, serial=3992, area=0xffffffff)
    at gdkgeometry-x11.c :1051
#3  0xb7a25b9d in gdk_event_translate (display=0x829a4d0, event=0x99e03c0, xevent=0xbf81eaf0,
    return_exposes=0) at gdkevents-x11.c:1484
#4  0xb7a266fd in _gdk_events_queue (display=0x829a4d0) at gdkevents-x11.c :2067
#5  0xb7a26891 in gdk_event_dispatch (source=0xffffffff, callback=0, user_data=0x0) at gdkevents-x11.c:2127
#6  0xb78dae4a in g_main_dispatch (context=0x82a51f8) at gmain.c:1895
#7  0xb78dbf28 in g_main_context_dispatch (context=0x82a51f8) at gmain.c:2441
#8  0xb78dc260 in g_main_context_iterate (context=0x82a51f8, block=1, dispatch=1, self=0x82d7be8)
    at gmain.c:2522
#9  0xb78dc8a3 in g_main_loop_run (loop=0x99e1660) at gmain.c:2726
#10 0xb7b62403 in gtk_main () at gtkmain.c:1172
#11 0x0809c07b in main (argc=1, argv=0xbf81ede4) at main.cc:260
(gdb) f 2
#2  0xb7a2c0a5 in _gdk_window_process_expose (window=0x9a38f18, serial=3992, area=0xffffffff)
    at gdkgeometry-x11.c:1051
1051                  queue_item_free (item);
(gdb) l
1046                }
1047              else
1048                {
1049                  queue_delete_link (display_x11->translate_queue,
1050                                     display_x11->translate_queue->head);
1051                  queue_item_free (item);
1052                }
1053            }
1054        }
1055
(gdb) p *(GdkWindowQueueItem *)tmp_list->data
$31 = {window = 0x9bbcc28, serial = 341, type = GDK_WINDOW_QUEUE_ANTIEXPOSE, u = {translate = {
      dx = 163135504, dy = 46399540}, antiexpose = {area = 0x9b94010}}}
(gdb) p *(GdkWindowQueueItem *)tmp_list->prev->data <= overflow
$32 = {window = 0x9a35d88, serial = 57, type = GDK_WINDOW_QUEUE_ANTIEXPOSE, u = {translate = {
      dx = 161749920, dy = 16}, antiexpose = {area = 0x9a41ba0}}}
(gdb) p *(GdkWindowQueueItem *)tmp_list->prev->prev->data      <=here, serial value is near the max ulong
$33 = {window = 0x9a36010, serial = 4294967176, type = GDK_WINDOW_QUEUE_ANTIEXPOSE, u = {translate = {
      dx = 161771960, dy = 52}, antiexpose = {area = 0x9a471b8}}}
(gdb) p *(GdkWindowQueueItem *)tmp_list->prev->prev->prev->data
$34 = {window = 0x9a36010, serial = 4294966893, type = GDK_WINDOW_QUEUE_ANTIEXPOSE, u = {translate = {
      dx = 161807208, dy = 16}, antiexpose = {area = 0x9a4fb68}}}

I know that serial will not overflow in the normal case, but when we need to build up some long standing application which keeps create windows, serial overflow seems unvoidable in the long run. So is there any way to reset serial to avoid the situation or this is really a bug in the gdk library itself. Any suggestion/comment is welcome. I attach the code of _gdk_window_process_expose for your reference purpose.

1017    void
1018    _gdk_window_process_expose (GdkWindow    *window,
1019                                gulong        serial,
1020                                GdkRectangle *area)
1021    {
1022      GdkWindowImplX11 *impl;
1023      GdkRegion *invalidate_region = gdk_region_rectangle (area);
1024      GdkRegion *clip_region;
1025      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
(gdb)
1026      impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
1027
1028      if (display_x11->translate_queue)
1029        {
1030          GList *tmp_list = display_x11->translate_queue->head;
1031
1032          while (tmp_list)
1033            {
1034              GdkWindowQueueItem *item = tmp_list->data;
1035              tmp_list = tmp_list->next;
(gdb)
1036
1037              if (serial < item->serial)
1038                {
1039                  if (item->window == window)
1040                    {
1041                      if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
1042                        gdk_region_offset (invalidate_region, item->u.translate.dx, item->u.translate.dy);
1043                      else          /* anti-expose */
1044                        gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
1045                    }
1046                }
1047              else
1048                {
1049                  queue_delete_link (display_x11->translate_queue,
1050                                     display_x11->translate_queue->head);
1051                  queue_item_free (item);
1052                }
1053            }
1054        }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]