[Twisted-Python] twistd stopService processing question

Ross Jekel ross at sourcelabs.com
Fri Jun 10 18:47:26 EDT 2005


I am building and xmlBlaster XML-RPC client/server to interact with the
xmlBlaster server. xmlBlaster really works best if the client sends a
disconnect API call before shutting down, otherwise you sometimes won't
be able to reconnect the client until the next heartbeat timesout.

I thought the best place way to do this would be to create a simple
service that could get notified via stopService(), then return the
deferred from the xmlrpc.Proxy.callRemote function for the XML-RPC
xmlBlaster disconnect API call.

The issue is that if I do this, everything seems to work but I get this
error raised when I ^C my service:

2005/06/10 15:30 PDT [QueryProtocol,client] Traceback (most recent call
last):
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/defer.py", line
328, in _runCallbacks
            self.result = callback(self.result, *args, **kw)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/base.py", line
384, in _cbContinueSystemEvent
            self._continueSystemEvent(eventType)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/base.py", line
392, in _continueSystemEvent
            callable(*args, **kw)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/base.py", line
353, in disconnectAll
            failure.Failure(main.CONNECTION_LOST))
        --- <exception caught here> ---
          File
"/usr/local/lib/python2.4/site-packages/twisted/python/log.py", line 56,
in callWithLogger
            return callWithContext({"system": lp}, func, *args, **kw)
          File
"/usr/local/lib/python2.4/site-packages/twisted/python/log.py", line 41,
in callWithContext
            return context.call({ILogContext: newCtx}, func, *args,
**kw)
          File
"/usr/local/lib/python2.4/site-packages/twisted/python/context.py", line
52, in callWithContext
            return self.currentContext().callWithContext(ctx, func,
*args, **kw)
          File
"/usr/local/lib/python2.4/site-packages/twisted/python/context.py", line
31, in callWithContext
            return func(*args,**kw)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/tcp.py", line
557, in connectionLost
            self.connector.connectionLost(reason)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/base.py", line
655, in connectionLost
            self.factory.clientConnectionLost(self, reason)
          File
"/usr/local/lib/python2.4/site-packages/twisted/web/xmlrpc.py", line
294, in clientConnectionLost
            self.deferred.errback(reason)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/defer.py", line
276, in errback
            self._startRunCallbacks(fail)
          File
"/usr/local/lib/python2.4/site-packages/twisted/internet/defer.py", line
303, in _startRunCallbacks
            raise AlreadyCalledError
        twisted.internet.defer.AlreadyCalledError:

I suppose I can probably ignore this but it makes it look like my
service isn't shutting down cleanly.

Any advice here? I include code snippets below to give you an idea what
I'm doing.

Ross

class SimpleService(service.Service):
    def stopService(self):
        global blaster
        return blaster.disconnect().addCallback(
            lambda res: service.Service.stopService(self))


# Create the application
a = service.Application("SMTP Server")

# Create a service wrapper so we can get notified of stopService
SimpleService().setServiceParent(service.IServiceCollection(a))

# Create an XML-RPC client/server for xmlBlaster
# TODO - come up with better server site creation
print 'INFO; Creating XML-RPC client/server'
s = SimpleSite()
blaster = xmlBlaster.xmlBlaster('http://127.0.0.2:8080', s)
internet.TCPServer(blaster.serverPort,
  server.Site(s)).setServiceParent(a)


xmlBlaster looks like this:

class xmlBlaster(xmlrpc.Proxy, xmlrpc.XMLRPC):
    def __init__(self, url, parent, serverPort = 7080):
        xmlrpc.Proxy.__init__(self, url)
        xmlrpc.XMLRPC.__init__(self)
        self.orig_url = url
        self.sessionId = None
        self.serverPort = serverPort
        self.subscriptions = {}
        parent.putChild('RC2', self)

    def disconnect(self):
        return self.callRemote('authenticate.disconnect',
            self.sessionId,
            "<qos/>).addCallback(self.__cbDisconnected)

    def __cbDisconnected(self, result):
        self.sessionId = None






More information about the Twisted-Python mailing list