Xpra: Ticket #1579: clipboard crash with shadow server

Easy to reproduce with Fedora 26:

Log output:

processing packet clipboard-request
clipboard_nesting_check(receiving, clipboard-request, X11ServerSource(1 : Protocol(unix-domain socket:/run/user/1000/xpra/desktop-2)))
process clipboard packet type=clipboard-request
process clipboard request, request_id=3, selection=CLIPBOARD, local name=CLIPBOARD, target=UTF8_STRING
get_contents(UTF8_STRING,<function got_contents at 0x7fffbd8e5050>) selection=CLIPBOARD, enabled=True, can-send=True
unpack <gtk.Clipboard object at 0x7fffc3318640 (GtkClipboard at 0x55555658fc90)>: <type 'gtk.SelectionData'>
unpack: <GtkSelectionData at 0x55555660edc0>

Backtrace:

#0  0x00007ffff6d18f96 in strlen () at /lib64/libc.so.6
#1  0x00007ffff7a92720 in PyString_FromString () at /lib64/libpython2.7.so.1.0
#2  0x00007fffe74d75ae in _wrap_gtk_selection_data__get_type (self=<optimized out>, closure=<optimized out>) at gtk.c:2160
#3  0x00007ffff7a75029 in getset_get.lto_priv () at /lib64/libpython2.7.so.1.0
#4  0x00007ffff7a973cc in _PyObject_GenericGetAttrWithDict () at /lib64/libpython2.7.so.1.0
#5  0x00007ffff7b0f40f in PyEval_EvalFrameEx (f=f@entry=Frame 0x555556670040, for file /usr/lib64/python2.7/site-packages/xpra/clipboard/clipboard_base.py, line 777, in unpack (clipboard=<gtk.Clipboard at remote 0x7fffc3318640>, selection_data=<gtk.SelectionData at remote 0x7fffbf3722b0>, user_data=None), throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:2617
#6  0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=(<cell at remote 0x7fffbd927ef8>, <cell at remote 0x7fffbd927de0>)) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#7  0x00007ffff7a541ce in function_call.lto_priv () at /lib64/libpython2.7.so.1.0
#8  0x00007ffff7a2bea3 in PyObject_Call () at /lib64/libpython2.7.so.1.0
#9  0x00007ffff7b09e97 in PyEval_CallObjectWithKeywords (func=<function at remote 0x7fffbd8e50c8>, arg=(<gtk.Clipboard at remote 0x7fffc3318640>, <gtk.SelectionData at remote 0x7fffbf3722b0>, None), kw=<optimized out>)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:4298
#10 0x00007fffe74f131b in clipboard_request_contents_cb (clipboard=0x55555658fc90, selection_data=<optimized out>, user_data=0x7fffc32f7170) at ./gtk.override:5016
#11 0x00007fffe6feed10 in selection_received () at /lib64/libgtk-x11-2.0.so.0
#12 0x00007fffe801730d in g_closure_invoke () at /lib64/libgobject-2.0.so.0
#13 0x00007fffe802998e in signal_emit_unlocked_R () at /lib64/libgobject-2.0.so.0
#14 0x00007fffe80321a5 in g_signal_emit_valist () at /lib64/libgobject-2.0.so.0
#15 0x00007fffe8032fe8 in g_signal_emit_by_name () at /lib64/libgobject-2.0.so.0
#16 0x00007fffe6f13b53 in gtk_selection_retrieval_report () at /lib64/libgtk-x11-2.0.so.0
#17 0x00007fffe6f15603 in gtk_selection_convert () at /lib64/libgtk-x11-2.0.so.0
#18 0x00007fffe74f1bc1 in _wrap_gtk_clipboard_request_contents (self=0x7fffc3318640, args=<optimized out>, kwargs=<optimized out>) at ./gtk.override:5046
#19 0x00007ffff7b12bce in call_function (oparg=<optimized out>, pp_stack=0x7fffffffbbf8) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4429
#20 0x00007ffff7b12bce in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#21 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x7fffd8006230, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#22 0x00007ffff7b10863 in fast_function (nk=0, na=<optimized out>, n=<optimized out>, pp_stack=0x7fffffffbdd8, func=<function at remote 0x7fffc331d140>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4524
#23 0x00007ffff7b10863 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffbdd8) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#24 0x00007ffff7b10863 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#25 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x7fffbe9f33c8, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#26 0x00007ffff7b10863 in fast_function (nk=0, na=<optimized out>, n=<optimized out>, pp_stack=0x7fffffffbfb8, func=<function at remote 0x7fffc331c500>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4524
#27 0x00007ffff7b10863 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffbfb8) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#28 0x00007ffff7b10863 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#29 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#30 0x00007ffff7a541ce in function_call.lto_priv () at /lib64/libpython2.7.so.1.0
#31 0x00007ffff7a2bea3 in PyObject_Call () at /lib64/libpython2.7.so.1.0
#32 0x00007ffff7a76e7e in instancemethod_call.lto_priv () at /lib64/libpython2.7.so.1.0
#33 0x00007ffff7a2bea3 in PyObject_Call () at /lib64/libpython2.7.so.1.0
#34 0x00007ffff7b09e97 in PyEval_CallObjectWithKeywords (func=<instancemethod at remote 0x7fffc29202d0>, arg=(['clipboard-request', 3, 'CLIPBOARD', 'UTF8_STRING'],), kw=<optimized out>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4298
#35 0x00007fffe825c4c9 in _pyglib_handler_marshal (user_data=0x7fffc32f7488) at pyglib.c:532
#36 0x00007fffe7b39c27 in g_idle_dispatch () at /lib64/libglib-2.0.so.0
#37 0x00007fffe7b3d247 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#38 0x00007fffe7b3d5e8 in g_main_context_iterate.isra () at /lib64/libglib-2.0.so.0
#39 0x00007fffe7b3d902 in g_main_loop_run () at /lib64/libglib-2.0.so.0
#40 0x00007fffe6ea40f7 in gtk_main () at /lib64/libgtk-x11-2.0.so.0
#41 0x00007fffe75b2b65 in _wrap_gtk_main (self=<optimized out>) at ./gtk.override:1240
#42 0x00007ffff7b12673 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffc6e8) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4413
#43 0x00007ffff7b12673 in PyEval_EvalFrameEx (f=f@entry=Frame 0x7fffc2bdc620, for file /usr/lib64/python2.7/site-packages/xpra/gtk_common/gtk_util.py, line 419, in gtk_main (), throwflag=throwflag@entry=0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#44 0x00007ffff7b111c9 in fast_function (nk=<optimized out>, na=<optimized out>, n=0, pp_stack=0x7fffffffc808, func=<function at remote 0x7fffe0947a28>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4514
#45 0x00007ffff7b111c9 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffc808) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#46 0x00007ffff7b111c9 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#47 0x00007ffff7b111c9 in fast_function (nk=<optimized out>, na=<optimized out>, n=1, pp_stack=0x7fffffffc928, func=<function at remote 0x7fffddc85578>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4514
#48 0x00007ffff7b111c9 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffc928) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#49 0x00007ffff7b111c9 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#50 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#51 0x00007ffff7a541ce in function_call.lto_priv () at /lib64/libpython2.7.so.1.0
#52 0x00007ffff7a2bea3 in PyObject_Call () at /lib64/libpython2.7.so.1.0
#53 0x00007ffff7a76e7e in instancemethod_call.lto_priv () at /lib64/libpython2.7.so.1.0
#54 0x00007ffff7a2bea3 in PyObject_Call () at /lib64/libpython2.7.so.1.0
#55 0x00007ffff7b0e884 in do_call (nk=0, na=<optimized out>, pp_stack=0x7fffffffce28, func=<instancemethod at remote 0x7fffc2e9c230>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4646
#56 0x00007ffff7b0e884 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffce28) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4451
#57 0x00007ffff7b0e884 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#58 0x00007ffff7b111c9 in fast_function (nk=<optimized out>, na=<optimized out>, n=1, pp_stack=0x7fffffffcf48, func=<function at remote 0x7fffddc7daa0>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4514
#59 0x00007ffff7b111c9 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffcf48) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
---Type <return> to continue, or q <return> to quit---
#60 0x00007ffff7b111c9 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named table.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#61 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x5555559b4110, kwcount=0, defs=0x7fffe9d8d668, defcount=1, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#62 0x00007ffff7b10863 in fast_function (nk=0, na=<optimized out>, n=<optimized out>, pp_stack=0x7fffffffd128, func=<function at remote 0x7fffe9d91a28>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4524
#63 0x00007ffff7b10863 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffd128) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#64 0x00007ffff7b10863 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#65 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x5555558c3fb0, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#66 0x00007ffff7b10863 in fast_function (nk=0, na=<optimized out>, n=<optimized out>, pp_stack=0x7fffffffd308, func=<function at remote 0x7fffec531500>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4524
#67 0x00007ffff7b10863 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffd308) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#68 0x00007ffff7b10863 in PyEval_EvalFrameEx (f=f@entry=Python Exception <class 'gdb.error'> There is no member named ob_ival.:
, throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#69 0x00007ffff7b111c9 in fast_function (nk=<optimized out>, na=<optimized out>, n=2, pp_stack=0x7fffffffd428, func=<function at remote 0x7fffec52eb90>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4514
#70 0x00007ffff7b111c9 in call_function (oparg=<optimized out>, pp_stack=0x7fffffffd428) at /usr/src/debug/Python-2.7.13/Python/ceval.c:4449
#71 0x00007ffff7b111c9 in PyEval_EvalFrameEx (f=f@entry=Frame 0x7ffff7e93790, for file /usr/bin/xpra, line 15, in <module> (), throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.13/Python/ceval.c:3063
#72 0x00007ffff7b13828 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=<optimized out>, args=<optimized out>, argcount=<optimized out>, kws=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0)
    at /usr/src/debug/Python-2.7.13/Python/ceval.c:3661
#73 0x00007ffff7b13a39 in PyEval_EvalCode (co=<optimized out>, globals=<optimized out>, locals=<optimized out>) at /usr/src/debug/Python-2.7.13/Python/ceval.c:691
#74 0x00007ffff7aee47f in run_mod () at /lib64/libpython2.7.so.1.0
#75 0x00007ffff7aee52a in PyRun_FileExFlags () at /lib64/libpython2.7.so.1.0
#76 0x00007ffff7aef52e in PyRun_SimpleFileExFlags () at /lib64/libpython2.7.so.1.0
#77 0x00007ffff7add0ae in Py_Main () at /lib64/libpython2.7.so.1.0
#78 0x00007ffff6ca54da in __libc_start_main () at /lib64/libc.so.6
#79 0x000055555555477a in _start ()

So it looks like the GtkSelectionData "type" is unset, and PyString_FromString crashes. We've seen this stacktrace before too: ticket:318#comment:5 (osx clipboard crash).



Wed, 19 Jul 2017 11:13:42 GMT - Antoine Martin: status changed; resolution set

Can also reproduce with a "start-desktop" instance when starting "gnome-shell". Dumping the GtkSelectionData using some cython code, I can see:

get_gtkselectiondata(<GtkSelectionData at 0x556e81e676c0>) boxed_get=0x556e81e676c0
selectiondata:
selection=69
target=71
type=0x556e81926e40
format=-0x477add80
length=-0x1
data=0x0

So it's just a simple NULL dereference. The pygtk code tries to copy a string of length=-1 at address zero... which never goes down well.

r16413 fixes this by patching the structure using some cython code to unwrap the boxed python object and set it to an empty string. This should be backported and looks like a GTK bug.


Thu, 20 Jul 2017 09:26:21 GMT - Antoine Martin:

Platform fix: r16424. (not available on win32 or macos)

Backports (patch made an awful mess): r16414 + r16415, fixups: r16418 + r16419

See also #1588.


Wed, 26 Jul 2017 16:15:28 GMT - Antoine Martin:

Regression reported, likely caused by this change: #1601


Wed, 26 Jul 2017 17:00:37 GMT - Antoine Martin: status, milestone changed; resolution deleted

The code has been disabled in older branches as of r16524.


Thu, 27 Jul 2017 14:55:06 GMT - Antoine Martin:

Should we re-enable this code, r16535 allows it to compile on all platforms. (tested on Linux and win32)


Sat, 29 Jul 2017 07:39:49 GMT - Antoine Martin:

The crash had stopped and now it's happening again (??):

xpra start-desktop :100 --start=xterm --no-daemon
xpra attach

then run metacity from the xterm.


Sat, 29 Jul 2017 16:16:44 GMT - Antoine Martin: status changed; resolution set

Better fix (I think) in r16560 - see commit message.

The big problem during testing was that even hooking the sanitation method was fixing things... looks like a heisenbug caused by a race condition somewhere. Making it difficult to see what values were causing the crash, as printing the values "fixed" things... So the fix isn't as clean as I would like, since there is no API for checking that a GdkAtom is valid. But things no longer crash, I think, and the clipboard still works.

And so I'm not going to backport this for now.


Fri, 11 Aug 2017 17:14:48 GMT - Antoine Martin:

Backport to 2.1 in r16681 + r16686, r16687 for v1.0.x branch.


Thu, 13 Sep 2018 15:57:37 GMT - Antoine Martin: status changed; resolution deleted

This code now triggers too much, causing log spam and missing clipboard data.


Thu, 13 Sep 2018 17:00:49 GMT - Antoine Martin: milestone changed

This needs to be sanitized because it causes a crash:

get_gtkselectiondata(<GtkSelectionData at 0x559abf3b1280>) type=<type 'gtk.SelectionData'>
selectiondata: selection=0x1, target=0x47, type=0x559abfaf8070, format=-0x1ba07280, length=-0x1, data=0x0
Warning: sanitizing invalid gtk selection type atom 0x559abfaf8070

Sun, 16 Sep 2018 06:11:08 GMT - Antoine Martin: status changed; resolution set


Sun, 28 Oct 2018 05:09:30 GMT - Antoine Martin:

Caused a regression: #2009


Sat, 23 Jan 2021 05:28:14 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/1579