[Twisted-Python] Reactor takes a long time to shutdown

I'm giving a talk "An introduction to Twisted" at PyconUK and am trying to come up with some simple examples. One of these, is the attached PortCheck module, that is supposed to attempt connection to a range of ports and report whether they're open, closed, filtered (timeout). It works okay when run against localhost, or another machine on my local network, but I've noticed that when I run it against an internet host, the reactor takes ages to shutdown after scanning all the ports. I wondered if there was anything obviously wrong with the code. Run it as follows from bash: python portcheck.py www.google.co.uk {1..1000} Thanks in advance for any suggestions. -RichardW.

Hi Richard, I tried your code and it works fine for me. The script always exits right away after scanning all ports. I tried various hosts and various port ranges. I'm running Python 2.4.4, Twisted 2.5.0, on OS X. btw: I would warn against port scanning public sites such as google; you don't want to trip an IDS and cop the wrath of a network admin. Hope this helps. Cya at PyConUK. Cheers, Chris On 25 Aug 2007, at 12:53, Richard Wall wrote:
I'm giving a talk "An introduction to Twisted" at PyconUK and am trying to come up with some simple examples.
One of these, is the attached PortCheck module, that is supposed to attempt connection to a range of ports and report whether they're open, closed, filtered (timeout).
It works okay when run against localhost, or another machine on my local network, but I've noticed that when I run it against an internet host, the reactor takes ages to shutdown after scanning all the ports. I wondered if there was anything obviously wrong with the code.
Run it as follows from bash: python portcheck.py www.google.co.uk {1..1000}
Thanks in advance for any suggestions.
-RichardW. """ A module to demonstrate some of the simplest twisted client code possible @author: Richard Wall <richard (at) the-moon.net> """ import sys
from twisted.internet import reactor from twisted.internet.defer import DeferredList from twisted.internet.task import Cooperator from twisted.internet.protocol import ClientCreator, Protocol from twisted.internet.error import ConnectionRefusedError, TimeoutError
STATUS_OPEN = "open" STATUS_CLOSED = "closed" STATUS_TIMEOUT = "timeout"
MAX_SIMULTANEOUS_CONNECTIONS = 100
def getPortStatus(host, port, timeout=1): """ Return a deferred that is called back with one of: open, closed, timeout @param host: The hostname or IP with which to attempt a connection @param port: The port to connect @param timeout: Number of seconds to wait for connection before giving up @return: A deferred which will call back with one of STATUS_{OPEN,CLOSED,TIMEOUT} """
cli = ClientCreator(reactor, Protocol)
d = cli.connectTCP(host, port, timeout=timeout)
def cb(proto): proto.transport.loseConnection() return STATUS_OPEN
def eb(err): expectedErrors = { ConnectionRefusedError: STATUS_CLOSED, TimeoutError: STATUS_TIMEOUT }
e = err.trap(*expectedErrors.keys()) if e: return expectedErrors[e]
d.addCallbacks(cb, eb)
return d
def main(argv): """ Command line access to the getPortStatus function. Pass me a hostname and one or more ports and I will report their status. """ host = argv[1] ports = map(int, argv[2:])
def cb(status, host, port): sys.stdout.write("%s:%d %s\n"%(host,port,status))
def eb(err): sys.stderr.write("%s\n" % err.value)
def portStatusGenerator(host, ports): for p in ports: d = getPortStatus(host, p) d.addCallbacks(cb, eb, (host, p)) yield d
# Limit parallelism otherwise we run out of file descriptors # See http://jcalderone.livejournal.com/24285.html work = portStatusGenerator(host, ports) coop = Cooperator() d = DeferredList( [coop.coiterate(work) for i in xrange (MAX_SIMULTANEOUS_CONNECTIONS)])
d.addCallback(lambda ign: reactor.stop()) reactor.run()
if __name__ == "__main__": sys.exit(main(sys.argv))
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Chris Miles wrote:
I tried your code and it works fine for me. The script always exits right away after scanning all ports. I tried various hosts and various port ranges. I'm running Python 2.4.4, Twisted 2.5.0, on OS X.
Chris, Thanks for trying it out. I'm working on Ubuntu Gutsy, Python2.5, Twisted trunk, Kernel 2.6.22. I just tried on a server running Ubuntu Dapper, Python2.4, kernel 2.6.15 and that shuts down straight away, as you found. Oh well.
btw: I would warn against port scanning public sites such as google; you don't want to trip an IDS and cop the wrath of a network admin.
I was using someone elses ADSL at the time :)
Hope this helps. Cya at PyConUK.
Yep, look forward to it. Assuming I finish the slides in time. ;) -RichardW.
participants (2)
-
Chris Miles
-
Richard Wall