Skip to content

ThreadedVNCClientProxy.disconnect() does not block until disconnection complete #314

@Jamie-

Description

@Jamie-

I use vncdotool synchronously via the API it exposes, my server is multi screen and I have two clients.
My code, simplified, looks something like this:

class X:
    def __init__(self):
        self._client1 = None
        self._client2 = None

    @property
    def client1(self):
        if not self._client1:
            client = api.connect(VNC_ADDRESS, password=VNC_PASSWORD, timeout=10)
            client.mouseMove(0, 0)
            self._client1 = client
        return self._client1

    @property
    def client2(self):
        if not self._client2:
            client = api.connect(VNC_ADDRESS + ":1", password=VNC_PASSWORD, timeout=10)
            client.mouseMove(0, 0)
            self._client2 = client
        return self._client2

    def reconnect_clients(self):
        self.log.info("Reinitializing device")
        if self._client1:
            self._client1.disconnect()
        if self._client2:
            self._client2.disconnect()
        self._client1 = None
        self._client2 = None
        do_stuff(self.client1)
        do_stuff(self.client2)

The vncdotool code for disconnect in api.py looks like this:

    def disconnect(self):
        def disconnector(protocol):
            protocol.transport.loseConnection()
        reactor.callFromThread(self.factory.deferred.addCallback, disconnector)

It schedules disconnector for execution but then returns before the connection has actually disconnected. As the function has returned in the main thread, my code carries on and tries to use the client again. I see regular issues where do_stuff(self.client1) blows up with TimeoutError: Timeout while waiting for client response (coming from proxy_call on ThreadedVNCClientProxy).
I think this is because my VNC server (TightVNC on Windows) is doing something racy and closes the new and old connections when the disconnect actually is executed by the reactor in certain cases.

I've not been able to reliably reproduce this in isolation, but the problem would be solved if ThreadedVNCClientProxy.disconnect() blocked until disconnection had actually occurred. Given ThreadedVNCClientProxy is acting as a syncronous API, it should also act synchronous here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions