Permalink
Browse files

vmnetx.ui.view: Fix missing guest mouse cursor in some sessions

We can't use channel.connect() to connect a GObject signal because
SpiceChannel overrides connect() to mean "initiate a TCP connection".
Instead, we were using channel.connect_object(..., channel), but this
creates a reference cycle between the channel PyGObject and the
underlying GObject.  With connect(), the PyGObject would be destroyed
after _new_channel() and recreated (pointing to the same GObject) before
the _request_fd() callback.  With connect_object(), the PyGObject is
referenced from the signal handler closure and so is never freed.
However, if the Python GC runs between _new_channel() and _request_fd(),
it will detect a reference cycle and clear the PyGObject's reference to
the GObject.  This was happening to the cursor channel on RHEL 6;
_request_fd() would receive an invalid PyGObject and then swallow the
resulting TypeError.  As a result, the cursor channel would never be
connected, and the guest cursor (for VMs supporting a hardware cursor)
would always be invisible.

Use connect() instead of connect_object(), explicitly calling it through
the superclass.
  • Loading branch information...
bgilbert committed May 23, 2014
1 parent 0f45078 commit 529b638d7c9368e67fb6064f6849ded5a55640d0
Showing with 6 additions and 6 deletions.
  1. +6 −6 vmnetx/ui/view.py
@@ -20,6 +20,7 @@
from distutils.version import LooseVersion
import glib
import gobject
from gobject import GObject
import gtk
import logging
import pango
@@ -285,23 +286,22 @@ def _connect_viewer(self, password):
except RuntimeError:
# No local PulseAudio, etc.
pass
self._session.connect_object('channel-new', self._new_channel,
self._session)
GObject.connect(self._session, 'channel-new', self._new_channel)
self._session.open_fd(-1)
def _new_channel(self, session, channel):
if session != self._session:
# Stale channel; ignore
return
channel.connect_object('open-fd', self._request_fd, channel)
channel.connect_object('channel-event', self._channel_event, channel)
GObject.connect(channel, 'open-fd', self._request_fd)
GObject.connect(channel, 'channel-event', self._channel_event)
type = SpiceClientGtk.spice_channel_type_to_string(
channel.get_property('channel-type'))
if type == 'display':
# Create the display but don't show it until configured by
# the server
channel.connect_object('display-primary-create',
self._display_create, channel)
GObject.connect(channel, 'display-primary-create',
self._display_create)
self._destroy_display()
self._display_channel = channel
self._display = SpiceClientGtk.Display(self._session,

0 comments on commit 529b638

Please sign in to comment.