Calls to daemon being blocked by executing code

Specific support for Deluge on Microsoft Windows OS
Post Reply
laharah
Member
Member
Posts: 26
Joined: Wed Jan 08, 2014 2:41 am

Calls to daemon being blocked by executing code

Post by laharah »

I'm not sure if I've got a bug on my hands or if I've misunderstood something basic. Either way I'm in need of help. I'm writing another client script to help me re-organize my media torrents. The problem I've run into is that new calls I make to the daemon from my client script are being blocked.

Here's a simple example script:

Code: Select all

from deluge.ui.client import client
from twisted.internet import reactor
import time

class SomeClasss():
    def __init__(self):
        self.torrents = {}

    def onConnect(self, result):
        print result
        client.core.get_torrents_status(None, ['name']).addCallback(self.populateTorrents)

    def populateTorrents(self, data):
        self.torrents = data
        firstTorrent = self.torrents[self.torrents.keys()[0]]['name']
        print firstTorrent, "should pause now!"
        client.core.pause_torrent([self.torrents.keys()[0]])
        self.doSomethingElse()

    def doSomethingElse(self):
        time.sleep(20)
        # torrent will not pause until control returns to onConnect
        print "Done Waiting"

    def on_error(self, result):
        print 'error connecting', result

def main():
    d = client.connect()
    MyClass = SomeClasss()
    d.addCallback(MyClass.onConnect)
    d.addErrback(MyClass.on_error)
    reactor.run()

if __name__ == '__main__':
    main()
As I understand it, since the call is being made asynchronously, the torrent should pause as soon as the daemon receives the call from client.core. However if you run the script above, the torrent won't pause until all other work is done. Nor will just about any call whatsoever execute.

I'm not sure if it's a bug or if there's something basic I'm misunderstanding. It's made my script more or less impossible to build. Can anyone help me out, or at least run the sample script and confirm that it's not just me?
Cas
Top Bloke
Top Bloke
Posts: 3681
Joined: Mon Dec 07, 2009 6:04 am
Location: Scotland

Re: Calls to daemon being blocked by executing code

Post by Cas »

It has to do with the Twisted reactor event loop.

The line client.core.pause_torrent registers the callback but it won't be run until after the rest of your code has been processed and your function doSomethingElse is blocking that loop.

This diagram from krondo.com tutorial might help understand this better:

Image
laharah
Member
Member
Posts: 26
Joined: Wed Jan 08, 2014 2:41 am

Re: Calls to daemon being blocked by executing code

Post by laharah »

Cas wrote: The line client.core.pause_torrent registers the callback but it won't be run until after the rest of your code has been processed and your function doSomethingElse is blocking that loop.


So how would I re-write my example so that the callback actually fires before my doSomethingElse function begins?


I understand what I was misunderstanding... after you add a client.core call you add a callback, and then the control has to fall all the way back to the reactor before the call gets sent to the daemon by the reactor. The code should look like this:

Code: Select all

def populateTorrents(self, data):
        self.torrents = data
        firstTorrent = self.torrents[self.torrents.keys()[0]]['name']
        print firstTorrent, "should pause now!"
        client.core.pause_torrent([self.torrents.keys()[0]]).addCallback(self.doSomethingElse)
        return

    def doSomethingElse(self, val):
        time.sleep(20)
        print "Done Waiting"
I was used to thinking about async programming with multiple threads, Just took my mind way to long to click async in single thread into place. Even managed to write 2 entire scripts without really understanding it :)
Cas
Top Bloke
Top Bloke
Posts: 3681
Joined: Mon Dec 07, 2009 6:04 am
Location: Scotland

Re: Calls to daemon being blocked by executing code

Post by Cas »

Yep that's it. Don't worry Twisted code lives up to its name :D
Post Reply