Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

avoid clipboard loops when running nested / sharing sessions #1312

Open
totaam opened this issue Sep 17, 2016 · 9 comments
Open

avoid clipboard loops when running nested / sharing sessions #1312

totaam opened this issue Sep 17, 2016 · 9 comments
Milestone

Comments

@totaam
Copy link
Collaborator

totaam commented Sep 17, 2016

Related to #41.

Create a UUID for each clipboard helper and add it to a root window property. Clients and servers forward their list of UUIDs to the other end, which then adds those to the root window property.
If any duplicates are found, we have a loop.

Another way of dealing with this is to set a random token on startup, prevent this token from ever being sent across, then looking for it at the other end. Any other clipboard synchronization tool will copy it, then we know we have a loop.

@totaam
Copy link
Collaborator Author

totaam commented Sep 17, 2016

2016-09-17 06:27:26: antoine uploaded file clipboard-loops.patch (6.6 KiB)

work in progress patch

@totaam
Copy link
Collaborator Author

totaam commented Jan 31, 2018

Done in r18229 (see commit message): we use a token which is never forwarded, then check for its presence at the other end.

Still TODO:

@totaam
Copy link
Collaborator Author

totaam commented Jan 31, 2018

Notifications and more done in r18230.

Keeping this ticket assigned to me as I have seen shadow server hangs in the clipboard code, which may be caused / made worse / related to this.

@totaam
Copy link
Collaborator Author

totaam commented Feb 2, 2018

Crashes and other problems should be gone as of r18248.

@maxmylyn: this ticket should ensure that we can coexist with other clipboard synchronization tools (ie: virtualbox, synergy, etc) and deal with it much more gracefully: disabling the clipboard and showing a notification to the user. Feel free to close.

@totaam
Copy link
Collaborator Author

totaam commented Feb 2, 2018

2018-02-02 17:04:23: maxmylyn commented

Excellent - noted.

Closing

@totaam
Copy link
Collaborator Author

totaam commented Apr 20, 2018

Hit a clipboard loop which was not detected: #1814

@totaam
Copy link
Collaborator Author

totaam commented Apr 25, 2018

2018-04-25 13:34:11: antoine commented


Finally got a clean reproducer without ssh start:

xpra shadow :1 --bind-tcp=0.0.0.0:10000 --no-daemon -d clipboard

From a win32 client which has clipboard synchronization already active through synergy, this usually works:

xpra attach tcp://192.168.1.8:10000/ -d clipboard

But this usually causes the server to hang:

xpra attach ssh://192.168.1.8/1 -d clipboard

Some of the weird exceptions I hit using these commands, or using a remote start via ssh: xpra start ssh://localhost/1:

Warning: more than 30 clipboard requests per second!
...
Warning: more than 30 clipboard requests per second!
 limit sustained for more than 3 seconds,
 the clipboard is now disabled
do_selection_get(<GtkSelectionData at 0x7fff027517c0>, 0, 45997266) selection=CLIPBOARD
Traceback (most recent call last):
  File "/usr/lib64/python2.7/site-packages/xpra/clipboard/clipboard_base.py", line 332, in _get_clipboard_from_remote_handler
    log("get clipboard from remote handler id=%s", request_id)
  File "/usr/lib64/python2.7/site-packages/xpra/log.py", line 392, in __call__
    self.log(logging.DEBUG, msg, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/xpra/log.py", line 388, in log
    global_logging_handler(self.logger.log, level, msg, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/xpra/log.py", line 132, in standard_logging
    log(level, msg, *args, **kwargs)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1231, in log
    self._log(level, msg, args, **kwargs)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1285, in _log
    record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1259, in makeRecord
    rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
  File "/usr/lib64/python2.7/logging/__init__.py", line 263, in __init__
    if (args and len(args) == 1 and isinstance(args[0], collections.Mapping)
  File "/usr/lib64/python2.7/abc.py", line 132, in __instancecheck__
    if subclass is not None and subclass in cls._abc_cache:
  File "/usr/lib64/python2.7/_weakrefset.py", line 72, in __contains__
    wr = ref(item)
RuntimeError: maximum recursion depth exceeded
remote selection fetch timed out or empty
error running cleanup <function cleanup_tcp_socket at 0x7f41d31ec668>
Traceback (most recent call last):
  File "/usr/lib64/python2.7/site-packages/xpra/scripts/server.py", line 33, in run_cleanups
    c()
  File "/usr/lib64/python2.7/site-packages/xpra/server/socket_util.py", line 129, in cleanup_tcp_socket
    log.info("closing %s socket %s:%s", socktype.lower(), host, iport)
  File "/usr/lib64/python2.7/site-packages/xpra/log.py", line 397, in info
    self.log(logging.INFO, msg, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/xpra/log.py", line 388, in log
    global_logging_handler(self.logger.log, level, msg, *args, **kwargs)
  File "/usr/lib64/python2.7/site-packages/xpra/log.py", line 132, in standard_logging
    log(level, msg, *args, **kwargs)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1231, in log
    self._log(level, msg, args, **kwargs)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1285, in _log
    record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
  File "/usr/lib64/python2.7/logging/__init__.py", line 1259, in makeRecord
    rv = LogRecord(name, level, fn, lno, msg, args, exc_info, func)
  File "/usr/lib64/python2.7/logging/__init__.py", line 285, in __init__
    self.threadName = threading.current_thread().name
  File "/usr/lib64/python2.7/threading.py", line 1157, in currentThread
    return _DummyThread()
  File "/usr/lib64/python2.7/threading.py", line 1125, in __init__
    Thread.__init__(self, name=_newname("Dummy-%d"))
  File "/usr/lib64/python2.7/threading.py", line 683, in __init__
    self.__started = Event()
  File "/usr/lib64/python2.7/threading.py", line 553, in Event
    return _Event(*args, **kwargs)
  File "/usr/lib64/python2.7/threading.py", line 565, in __init__
    _Verbose.__init__(self, verbose)
RuntimeError: maximum recursion depth exceeded in __instancecheck__

@totaam
Copy link
Collaborator Author

totaam commented Apr 26, 2018

Another interesting data point is that switching to schedule_emit_token for all owner change events makes things worse.

@totaam
Copy link
Collaborator Author

totaam commented Dec 12, 2019

Meh.
Now that the clipboard uses native API calls (#812), this no longer causes crashes.
I don't think that the loop detection code works properly, so maybe we should just remove it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant