After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 598476 - gnome-screensaver crashes when entering password incorrectly 5 times
gnome-screensaver crashes when entering password incorrectly 5 times
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: X11
2.18.x
Other Linux
: Normal blocker
: ---
Assigned To: gtk-bugs
gtk-bugs
: 603652 (view as bug list)
Depends on:
Blocks: 603652
 
 
Reported: 2009-10-14 18:19 UTC by Chris Coulson
Modified: 2010-02-05 18:18 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Debug output from gnome-screensaver leading up to the crash (311.70 KB, text/plain)
2009-10-14 18:21 UTC, Chris Coulson
  Details
gs_dont_crash_on_invalid_password.patch (3.85 KB, patch)
2009-11-02 23:46 UTC, Chris Coulson
committed Details | Review
xtrace log (81.51 KB, application/x-lzma)
2009-12-07 18:13 UTC, Chris Coulson
  Details
Possible gtk fix (735 bytes, patch)
2009-12-08 14:53 UTC, Alexander Larsson
committed Details | Review

Description Chris Coulson 2009-10-14 18:19:44 UTC
As reported here: https://bugs.edge.launchpad.net/ubuntu/+source/gnome-screensaver/+bug/446395

We're seeing several users reporting that their screen unlocks successfully when they enter their password incorrectly 5 times. What seems to be happening is that gnome-screensaver is actually crashing. I can trigger it sometimes (although I have to be quite persistent), and this is the backtrace I got (breaking on gdk_x_error):

  • #0 gdk_x_error
    at /build/buildd/gtk+2.0-2.18.2/gdk/x11/gdkmain-x11.c line 438
  • #1 _XError
    at ../../src/XlibInt.c line 2924
  • #2 process_responses
    at ../../src/xcb_io.c line 207
  • #3 _XReply
    at ../../src/xcb_io.c line 457
  • #4 XSync
    at ../../src/Sync.c line 48
  • #5 _XSyncFunction
    at ../../src/Synchro.c line 37
  • #6 XFreePixmap
    at ../../src/FreePix.c line 43
  • #7 gdk_pixmap_impl_x11_dispose
    at /build/buildd/gtk+2.0-2.18.2/gdk/x11/gdkpixmap-x11.c line 103
  • #8 IA__g_object_unref
    at /build/buildd/glib2.0-2.22.2/gobject/gobject.c line 2441
  • #9 gdk_pixmap_finalize
    at /build/buildd/gtk+2.0-2.18.2/gdk/gdkpixmap.c line 231
  • #10 IA__g_object_unref
    at /build/buildd/glib2.0-2.22.2/gobject/gobject.c line 2472
  • #11 gdk_window_end_implicit_paint
    at /build/buildd/gtk+2.0-2.18.2/gdk/gdkwindow.c line 2630
  • #12 gdk_window_process_updates_internal
    at /build/buildd/gtk+2.0-2.18.2/gdk/gdkwindow.c line 5241
  • #13 IA__gdk_window_process_all_updates
    at /build/buildd/gtk+2.0-2.18.2/gdk/gdkwindow.c line 5328
  • #14 gtk_container_idle_sizer
    at /build/buildd/gtk+2.0-2.18.2/gtk/gtkcontainer.c line 1353
  • #15 gdk_threads_dispatch
    at /build/buildd/gtk+2.0-2.18.2/gdk/gdk.c line 506
  • #16 g_main_dispatch
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 1960
  • #17 IA__g_main_context_dispatch
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 2513
  • #18 g_main_context_iterate
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 2591
  • #19 IA__g_main_context_iteration
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 2654
  • #20 IA__gtk_main_iteration
    at /build/buildd/gtk+2.0-2.18.2/gtk/gtkmain.c line 1304
  • #21 shake_dialog
    at gs-window-x11.c line 1420
  • #22 lock_command_watch
    at gs-window-x11.c line 1456
  • #23 g_main_dispatch
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 1960
  • #24 IA__g_main_context_dispatch
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 2513
  • #25 g_main_context_iterate
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 2591
  • #26 IA__g_main_loop_run
    at /build/buildd/glib2.0-2.22.2/glib/gmain.c line 2799
  • #27 IA__gtk_main
    at /build/buildd/gtk+2.0-2.18.2/gtk/gtkmain.c line 1216
  • #28 main
    at gnome-screensaver.c line 111


The X error is:

The program 'gnome-screensaver' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadDrawable (invalid Pixmap or Window parameter)'.
  (Details: serial 33949 error_code 9 request_code 53 minor_code 0)
  (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.)
Comment 1 Chris Coulson 2009-10-14 18:21:10 UTC
Created attachment 145446 [details]
Debug output from gnome-screensaver leading up to the crash
Comment 2 Chris Coulson 2009-10-16 07:34:15 UTC
We've just committed a change in Ubuntu which fixes this issue: http://bazaar.launchpad.net/~ubuntu-desktop/gnome-screensaver/ubuntu/revision/42#debian/patches/08_gs_dialog_request_to_exit.patch

Basically, what is happening is that gnome-screensaver-dialog exits after the 5th failed attempt at unlocking the screen, but before the shake animation finishes. If the timing is slightly unlucky, this results in gnome-screensaver accessing X resources that have already been destroyed (I ran it through xtrace, and that showed this happening)

My patch fixes this by making gnome-screensaver-dialog request to gnome-screensaver that it be terminated after the 5th failed attempt (rather than exitting straight away, although there is a fallback timeout too). gnome-screensaver then terminates the dialog after it is finished with the shake animation, to avoid the race condition that is currently making it crash.
Comment 3 Matthias Clasen 2009-10-17 18:11:08 UTC
Wouldn't it be much simpler to just ignore X errors in the shaker ?
Comment 4 Chris Coulson 2009-10-17 22:21:29 UTC
It would be simpler - but you still occasionally end up with quite a few g_critical messages on the console if you do it this way (although I can't tell you exactly what they are yet until I trigger it again).

The method I've used avoids this, and also means that the dialog only disappears after the shaker has finished (although that is mainly cosmetic)
Comment 5 William Jon McCann 2009-11-02 21:41:54 UTC
Can you please attach the patch here for review.  It doesn't look quite right to me.
Comment 6 Ray Strode [halfline] 2009-11-02 21:56:44 UTC
don't you need to queue a SIGTERM after the shake finishes if the request comes in while the shake is happening?  Also, I don't think this makes sense:

+ g_timeout_add (5000, (GSourceFunc)quit_timeout_cb, NULL);

There's no reason to second guess the daemon.
Comment 7 Ray Strode [halfline] 2009-11-02 21:58:56 UTC
Also, we should have the gdk_error_trap_push/gdk_display_sync/gdk_error_trap_pop calls comment 3 alluded to regardless for general robustness reasons.
Comment 8 Chris Coulson 2009-11-02 23:46:14 UTC
Created attachment 146788 [details] [review]
gs_dont_crash_on_invalid_password.patch

Here is the version of the patch which is currently applied in Ubuntu.

+ g_timeout_add (5000, (GSourceFunc)quit_timeout_cb, NULL);

This part was added to handle upgrades where the user might be running the old daemon but have a new gnome-screensaver-dialog process. Without this, the user is left with a hung dialog if they enter their password incorrectly 5 times after they upgraded, but before restarting their session.

I agree that we should probably have the gdk_error_trap_push/gdk_display_sync/gdk_error_trap_pop in addition to the change I've already made.

I removed the SIGTERM handler in our Ubuntu patch, as that caused other issues (such as the dialog hanging when it times out)
Comment 9 Ray Strode [halfline] 2009-12-04 19:46:48 UTC
So looking at this further, I think we may be missing the boat here.  Or at least, not entirely understanding the problem.

Trace 218314

shows the BadDrawable is a locally created pixmap that's internal to gtk, used for its expose handling.

Also, if you look at the more complete trace in launchpad (http://paste.ubuntu.com/293307/):

  • #6 XFreePixmap

it shows the pixmap being passed to XFreePixmap is bogus

That leads me to think we're dealing with some sort of memory corruption here.

Note I've spent some time trying to reproduce and have been unable to do so, so far.  

I also tried to induce the original race condition by adding sleep statements in the expose handler, by removing the sleeps in the shake function, by making it shaking indefinitly instead of 9 times, and by making the lock dialog exit after 1 failure instead of 5.

I also ran the screensaver through valgrind and haven't hit any issues yet.  Chris, can you:

1) try backing out your patch
2) make sure you can still reproduce the problem
3) export G_SLICE=always-malloc
4) run valgrind --log-file=/tmp/screensaver.log gnome-scrensaver --no-daemon
5) reproduce

and see if the valgrind log shows anything?
Comment 10 Chris Coulson 2009-12-07 18:13:17 UTC
Created attachment 149284 [details]
xtrace log

As discussed on IRC, here is a xtrace log I saved when initially debugging this issue some time ago. It's quite big, so I'll pick out the interesting bits here (and sorry for the compression, but it was the only way I could get it to below 100kB):

The errors that make it crash can be seen at the end of the file:

000:<:06be: 16: Request(53): CreatePixmap depth=0x18 pid=0x02e000fe drawable=0x05400020 width=550 height=362
000:<:06bf:  8: Request(54): FreePixmap drawable=0x02e000fe
000:<:06c0: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={cursor=None(0x00000000)}
000:<:06c1: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=None(0x00000000)}
000:<:06c2:  8: Request(10): UnmapWindow window=0x02e00060
000:<:06c3: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
000:<:06c4: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=None(0x00000000)}
000:<:06c5:  8: Request(10): UnmapWindow window=0x02e00060
000:<:06c6: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
000:<:06c7: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=None(0x00000000)}
000:<:06c8: 16: SHAPE-Request(141,1): ShapeRectangles operation=Set(0x00) destination kind=Bounding(0x00) ordering=YXBanded(0x03) destination window=0x02e00060 x-offset=0 y-offset=0 rectangles=;
000:<:06c9: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
000:<:06ca:  8: Request(4): DestroyWindow window=0x02e00060
000:<:06cb: 16: Request(53): CreatePixmap depth=0x18 pid=0x02e000ff drawable=0x02e00024 width=1680 height=1050
000:<:06cc: 28: Request(55): CreateGC cid=0x02e00100 drawable=0x02e000ff  values={fill-style=Tiled(0x01) tile=0x02e0004e graphics-exposures=false(0x00)}
000:<:06cd: 20: Request(59): SetClipRectangles ordering=YXBanded(0x03) gc=0x02e00100 clip-x-origin=0 clip-y-origin=0 rectangles ={x=0 y=0 w=1680 h=1050};
000:<:06ce: 20: Request(70): PolyFillRectangle drawable=0x02e000ff gc=0x02e00100 rectangles={x=0 y=0 w=1680 h=1050};
000:<:06cf:  8: Request(60): FreeGC gc=0x02e00100
000:<:06d0: 16: Request(2): ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
000:<:06d1: 28: Request(55): CreateGC cid=0x02e00101 drawable=0x02e000ff  values={fill-style=Tiled(0x01) tile=0x02e0004e graphics-exposures=false(0x00)}
000:<:06d2: 20: Request(59): SetClipRectangles ordering=YXBanded(0x03) gc=0x02e00101 clip-x-origin=0 clip-y-origin=0 rectangles ={x=0 y=0 w=1680 h=1050};
000:<:06d3: 20: Request(70): PolyFillRectangle drawable=0x02e000ff gc=0x02e00101 rectangles={x=0 y=0 w=1680 h=1050};
000:<:06d4:  8: Request(60): FreeGC gc=0x02e00101
000:<:06d5: 20: Request(59): SetClipRectangles ordering=YXBanded(0x03) gc=0x02e00056 clip-x-origin=0 clip-y-origin=0 rectangles ={x=0 y=0 w=1680 h=1050};
000:<:06d6: 28: Request(62): CopyArea src-drawable=0x02e000ff dst-drawable=0x02e00024 gc=0x02e00056 src-x=0 src-y=0 dst-x=0 dst-y=0 width=1680 height=1050
000:<:06d7: 16: Request(56): ChangeGC gc=0x02e00056  values={clip-mask=None(0x00000000)}
000:<:06d8:  8: Request(54): FreePixmap drawable=0x02e000ff
000:>:6be:Error 9=Drawable: major=0, minor=53, bad=88080416
000:>:6bf:Error 4=Pixmap: major=0, minor=54, bad=48234750

The first bad call is a CreatePixmap, which passes drawable=0x05400020. If you look above this in the log file, you will see that the server already sent out a DestroyNotify for this drawable:

000:>:06af: Event UnmapNotify(18) event=0x05400020 window=0x05400020 from-configure=false(0x00)
000:>:06af: Event UnmapNotify(18) event=0x02e00060 window=0x05400020 from-configure=false(0x00)
000:>:06af: Event Expose(12) window=0x02e00060 x=0 y=0 width=550 height=362 count=0x0000
000:>:06af: Event EnterNotify(7) detail=Inferior(0x02) mode=Normal(0x00) flags=same-screen time=0x02809425 root=0x0000013c event=0x02e00060 child=None(0x00000000) root-x=921 root-y=685 event-x=371 event-y=341 state=Mod2
000:>:06af: Event DestroyNotify(17) event=0x05400020 window=0x05400020
000:>:06af: Event DestroyNotify(17) event=0x02e00060 window=0x05400020

Looking further up in the log file, this particular drawable was created here:

003:<:00cc:  8: Request(17): GetAtomName atom=0xc7(unrecognized atom)
003:>:00cc:44: Reply to GetAtomName:  name='Mouse Keys'
003:<:00cd: 52: Request(1): CreateWindow depth=0x18 window=0x05400020 parent=0x0000013c x=0 y=0 width=1 height=1 border-width=0 class=InputOutput(0x0001) visual=0x00000021  value-list={background-pixel=0x00000000 border-pixel=0x00000000 bit-gravity=NorthWest(0x01) event-mask=KeyPress,KeyRelease,ButtonPress,ButtonRelease,EnterWindow,LeaveWindow,PointerMotion,Exposure,VisibilityChange,StructureNotify,PropertyChange colormap=0x00000020}
003:<:00ce: 48: Request(18): ChangeProperty mode=Replace(0x00) window=0x05400020 property=0x100("_NET_WM_NAME") type=0xf1("UTF8_STRING")     data=0x67,0x6e,0x6f,0x6d,0x65,0x2d,0x73,0x63,0x72,0x65,0x65,0x6e,0x73,0x61,0x76,0x65,0x72,0x2d,0x64,0x69,0x61,0x6c,0x6f,0x67;
003:<:00cf: 48: Request(18): ChangeProperty mode=Replace(0x00) window=0x05400020 property=0x27("WM_NAME") type=0x1f("STRING")    data='gnome-screensaver-dialog'
003:<:00d0: 48: Request(18): ChangeProperty mode=Replace(0x00) window=0x05400020 property=0xff("_NET_WM_ICON_NAME") type=0xf1("UTF8_STRING")     data=0x67,0x6e,0x6f,0x6d,0x65,0x2d,0x73,0x63,0x72,0x65,0x65,0x6e,0x73,0x61,0x76,0x65,0x72,0x2d,0x64,0x69,0x61,0x6c,0x6f,0x67;

The numbers on the left there indicate that these calls were from a different process, and the ChangeProperty calls show that gnome-screensaver-dialog created this window.

Basically, what seems to be happening is that the GdkWindow passed to gdk_window_process_updates_internal() is actually the newly destroyed foreign window belonging to gnome-screensaver-dialog, and this is where the 2 failed calls shown in the xtrace log come from (CreatePixmap in gdk_window_begin_implicit_paint, and FreePixmap in gdk_window_end_implicit_paint).
Comment 11 Ray Strode [halfline] 2009-12-07 22:57:49 UTC
> CreateWindow depth=0x18 window=0x02e00024 parent=0x0000013c x=0 y=0 width=1680 height=1050 border-width=0 class=InputOutput(0x0001) visual=0x00000021  value-list={background-pixel=0x00000000 border-pixel=0x00000000 bit-gravity=NorthWest(0x01) override-redirect=true(0x01) save-under=true(0x01) event-mask=KeyPress,KeyRelease,ButtonPress,ButtonRelease,EnterWindow,LeaveWindow,PointerMotion,Exposure,VisibilityChange,StructureNotify,FocusChange,PropertyChange colormap=0x02e00023}
> ChangeProperty mode=Replace(0x00) window=0x02e00024 property=0x100("_NET_WM_NAME") type=0xf1("UTF8_STRING")     data=0x67,0x6e,0x6f,0x6d,0x65,0x2d,0x73,0x63,0x72,0x65,0x65,0x6e,0x73,0x61,0x76,0x65,0x72;
> ChangeProperty mode=Replace(0x00) window=0x02e00024 property=0x27("WM_NAME") type=0x1f("STRING")    data='gnome-screensaver'

So 0x02e00024 is the fullscreen screensaver window

[...]
> CreateWindow depth=0x18 window=0x05400020 parent=0x0000013c x=0 y=0 width=1 height=1 border-width=0 class=InputOutput(0x0001) visual=0x00000021  value-list={background-pixel=0x00000000 border-pixel=0x00000000 bit-gravity=NorthWest(0x01) event-mask=KeyPress,KeyRelease,ButtonPress,ButtonRelease,EnterWindow,LeaveWindow,PointerMotion,Exposure,VisibilityChange,StructureNotify,PropertyChange colormap=0x00000020}
[...]
> ChangeProperty mode=Replace(0x00) window=0x05400020 property=0x27("WM_NAME") type=0x1f("STRING")    data='gnome-screensaver-dialog'
And 0x05400020 is the lock dialog running in a subprocess.

[...]
> CreateWindow depth=0x18 window=0x02e00060 parent=0x02e00024 x=-1 y=-1 width=1 height=1 border-width=0 class=InputOutput(0x0001) visual=0x00000021  value-list={background-pixel=0x00e6ddd5 border-pixel=0x00000000 bit-gravity=NorthWest(0x01) event-mask=EnterWindow,LeaveWindow,Exposure,VisibilityChange,StructureNotify,FocusChange,PropertyChange colormap=0x02e00023}
Here we create a child of the fullscreen screensaver window

[...]
> ReparentWindow window=0x05400020 parent=0x02e00060 x=0 y=0
> InternAtom only-if-exists=false(0x00)  name='_XEMBED_INFO'
And here we reparent the lock dialog from the subprocess into that child of the fullscreen window.
This means the child of the fullscreen screensaver window (0x02e00060) is a gtk socket.

So now we know who the players are:
0x02e00024 - fullscreen screensaver window
0x02e00060 - gtk socket in the parent
0x05400020 - lock dialog plug

[...]
> CreatePixmap depth=0x18 pid=0x02e000fb drawable=0x02e00024 width=1680 height=1050
Here we create a backing pixmap 0x02e000fb for the fullscreen screensaver window

[...]
> PolyFillRectangle drawable=0x02e000fb gc=0x02e000fc rectangles={x=0 y=0 w=1680 h=1050};
[...]
> PolyFillRectangle drawable=0x02e000fb gc=0x02e000fd rectangles={x=0 y=0 w=1680 h=1050};
Here we fill the backing pixmap with data

[...]
> CopyArea src-drawable=0x02e000fb dst-drawable=0x02e00024 gc=0x02e00056 src-x=0 src-y=0 dst-x=0 dst-y=0 width=1680 height=1050
[...]
> FreePixmap drawable=0x02e000fb
Here we copy the data from the backing pixmap to the fullscreen screensaver window and then free
the backing pixmap, so this was just a bit of double buffered drawing.

[...]
> CreatePixmap depth=0x18 pid=0x02e0004e drawable=0x02e00024 width=1 height=1
> CreateGC cid=0x02e0004f drawable=0x02e0004e  values={graphics-exposures=false(0x00)}
> PolyPoint coordinate-mode=Origin(0x00) drawable=0x02e0004e gc=0x02e0004f points={x=0 y=0};
Here we create a 1x1 solid tile pixmap that gets used later

[...]
> CreatePixmap depth=0x18 pid=0x02e000fe drawable=0x05400020 width=550 height=362
Here we create (from the parent process) a backing pixmap 0x2e000fe for the
lock dialog plug (which is running in the child process)

> FreePixmap drawable=0x02e000fe
Here we immediately free the backing pixmap.  Note we did no double buffered drawing,
at all.  This sort of makes sense.  The child is doing the drawing not us.  GTK+ probably
shouldn't have made the back pixmap in the first place, though.

[...]
> ChangeWindowAttributes window=0x02e00024  value-list={cursor=None(0x00000000)}
> ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=None(0x00000000)}
Here we're messing around with the screensaver window again, not fooling with the lock dialog anymore
> UnmapWindow window=0x02e00060
> ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
> ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=None(0x00000000)}
Here we unmap the socket.  We must have gotten a lock-plug-removed signal.
The handler for that does:

        gtk_widget_hide (widget);

which would ultimately cause an UnmapWindow.

> UnmapWindow window=0x02e00060
> ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
> ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=None(0x00000000)}
rinse and repeat? Huh?

> ShapeRectangles operation=Set(0x00) destination kind=Bounding(0x00) ordering=YXBanded(0x03) destination window=0x02e00060 x-offset=0 y-offset=0 rectangles=;
Then we set the shape of the socket window to be empty (no rectangles in the list),
even though it's unmapped.  I think this means if it were mapped again it wouldn't show up
at all.  That's sort of strange, but it's probably some subtle toolkit magic to
prevent some misbehavior from happening or something.  Maybe it's a workaround for a
buggy window manager.  I'm not sure.  I dont' think it's related to our problem, though.

> ChangeWindowAttributes window=0x02e00024  value-list={background-pixmap=0x02e0004e}
> DestroyWindow window=0x02e00060
We now explicitly destroy the socket window.  That's probably from this line in the
lock-plugin-removed handler:

        gtk_container_remove (GTK_CONTAINER (window->priv->vbox),
                              GTK_WIDGET (window->priv->lock_box));

We remove the socket from the parent window, which drops the socket's ref count to 0, causing
the socket to get destroyed.

> CreatePixmap depth=0x18 pid=0x02e000ff drawable=0x02e00024 width=1680 height=1050
[...]
> PolyFillRectangle drawable=0x02e000ff gc=0x02e00100 rectangles={x=0 y=0 w=1680 h=1050};
[...]
> PolyFillRectangle drawable=0x02e000ff gc=0x02e00101 rectangles={x=0 y=0 w=1680 h=1050};
[...]
> CopyArea src-drawable=0x02e000ff dst-drawable=0x02e00024 gc=0x02e00056 src-x=0 src-y=0 dst-x=0 dst-y=0 width=1680 height=1050
> FreePixmap drawable=0x02e000ff
We do another round of double-buffered drawing to the fullscreen screensaver window

At this point we must have gone back to the main loop because the next line says ...

> Error 9=Drawable: major=0, minor=53, bad=88080416
Uh oh, X error.  88080416 is 0x5400020 in hex, that's our lock dialog plug
minor=53 is CreatePixmap

> Error 4=Pixmap: major=0, minor=54, bad=48234750
Uh oh, another X error.  48234750 is 0x02e000fe in hex, thats the backing pixmap
for the lock dialog plug we created and free'd immediately afterward without doing anything
to it.

minor=54 is FreePixmap

So the FreePixmap request is failing because the CreatePixmap request failed initially.

Okay, so the problem is gtk is calling CreatePixmap and passing in a foreign drawable that
no longer exists.  Let's look at the code probably at fault:

static void
gdk_window_process_updates_internal (GdkWindow *window)
{
   ...
   end_implicit = gdk_window_begin_implicit_paint (window, &clipbox) {
       ...
       paint->pixmap = gdk_pixmap_new (window, clipbox->width, clipbox->height, -1) {
           ...
           pixmap->xid = XCreatePixmap (display, window, clipbox->width, clipbox->height, -1);
           pixmap->is_foreign = FALSE;
           ...
           return pixmap;
       }
       ...
       return paint;
   }
   ...
   gdk_window_end_implicit_paint (window) {
       ...
       g_object_unref (paint->pixmap) {
           ...
           if (!pixmap->is_foreign) {
              XFreePixmap (display, pixmap->xid);
           }
           ...
       }
   }
   ...
}

So the socket's plug window must be getting added to the list of windows to process by
gdk_window_process_updates_internal.  I don't know if that's right or not.

If it is right, maybe it should have a if (FOREIGN) gdk_error_trap pop / push wrapping the function.

Or maybe this is just something we're supposed to deal with on the screensaver side.  Alex, do you have any insight here?
Comment 12 Ray Strode [halfline] 2009-12-08 13:48:20 UTC
I found alex, conversation below:

<halfline> alex: basically the screensaver has a lock dialog plug that fits into a socket in the fullscreen screensaver window
<halfline> alex: if the lock dialog process quits, the plug disappears           
<halfline> alex: if that happens under the right circumstances then gtk will generate an X error becuase it's trying to create a backing pixmap using the plug as a reference drawable
<halfline> alex: so i'm wondering 1) should gtk avoid using a foreign window as a reference drawable for the implicit paint pixmap ?
<halfline> 2) if not, should it add its own guards against that foreign window going away
<halfline> or                                                                
<halfline> should gnome-screensaver just deal                                
<alex> If the user specifies exposure events in the foreign window it'll get events and the will trigger the double buffering
<alex> gtk+ should handle this but i don't which of 1) or 2) is the best 
<alex> Technically i guess the child foreign window could have a different visual
<alex> which seems to imply that we want to do 2?
<halfline> sounds reasonable to me, but i'm probably not the best person to ask            
* alex is sort of busy right now so can't look into it in more detail at the moment                       
<halfline> okay, i'll paste this into the bug report
<halfline> what i really want to find out i guess is who is affected
<halfline> i'll dig a bit
<alex> how did it not happen before?
<alex> i guess the double buffering stuff changed
<halfline> everyone who's seen it has been running 2.18 afaict
Comment 13 Alexander Larsson 2009-12-08 14:53:21 UTC
Created attachment 149335 [details] [review]
Possible gtk fix

I think an easy solution might be to not do implicit painting for foreign windows, as its risky and is not useful.
Comment 14 Matthias Clasen 2009-12-08 14:54:45 UTC
Looks like a good idea to me.
Comment 15 Michal Hruby 2010-01-25 19:38:49 UTC
Shouldn't someone with the appropriate privileges change "Product" to gtk+?
Comment 16 Matthias Clasen 2010-01-25 20:24:06 UTC
Comment on attachment 149335 [details] [review]
Possible gtk fix

This has been committed a while ago
Comment 17 Chris Coulson 2010-02-05 10:20:11 UTC
I dropped the Ubuntu patch for gnome-screensaver some time ago, and we have the GTK version with the above commit in. I don't see this crash any more (and I've not seen anybody report the issue again), so I'm closing this as fixed now. Thanks!
Comment 18 Michal Hruby 2010-02-05 14:25:35 UTC
*** Bug 603652 has been marked as a duplicate of this bug. ***
Comment 19 Ray Strode [halfline] 2010-02-05 18:18:26 UTC
Comment on attachment 146788 [details] [review]
gs_dont_crash_on_invalid_password.patch

FWIW, mccann commited your patch about a week ago:

http://git.gnome.org/browse/gnome-screensaver/commit/?id=ab08cc93f2dc6223c8c00bfa1ca4f2d89069dbe0