Hi Steve,
This email may read a little odd. I've been writing this whilst reading and trying things out, saw your update, and having had a thought. As a result the train of thought changes as I go through this, but I've left that in since it may be of use. On Monday 02 March 2009 21:11:53 Steve wrote: .. > TCPClient('127.0.0.1', 80).run() > > I have no server running on port 80 so it should timeout and return. > Instead it tries (in a seemingly infinite loop) to make the connection. My > software firewall (set to allow all) reports around 1 connection attempt > every second. That's rather odd. I've just tried the same thing here, and I don't see any looping attempt to connect - it fails to connect and exits straight away: ~> python Python 2.5.1 (r251:54863, Jan 10 2008, 18:01:57) [GCC 4.2.1 (SUSE Linux)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from Kamaelia.Internet.TCPClient import TCPClient >>> TCPClient("127.0.0.1", 81).run() >>> That said, I'm not running a firewall though... I've also checked that it's passing on shutdown correctly. First the case that doesn't exit, until control-c : >>> from Kamaelia.Chassis.Pipeline import Pipeline >>> from Kamaelia.Util.Console import ConsoleEchoer >>> Pipeline( ConsoleEchoer() ).run() And then a version that does exit because the TCPClient passes on it's shutdown on error: ~> python Python 2.5.1 (r251:54863, Jan 10 2008, 18:01:57) [GCC 4.2.1 (SUSE Linux)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from Kamaelia.Chassis.Pipeline import Pipeline >>> from Kamaelia.Util.Console import ConsoleEchoer >>> from Kamaelia.Internet.TCPClient import TCPClient >>> Pipeline( TCPClient("127.0.0.1", 81), ConsoleEchoer() ).run() >>> All this tells me is that the situation I've tested it in and mainly used it in still works as expected. This isn't the same as your situation. As a result, I'm no real information up - I'm not reproducing your behaviour/environment correctly yet. I'm beginning to think I ought to start up a windows VM and see if I can reproduce this there. > The end result is that I believe Kamaelia (or the socket layer) is not > properly handling a silently refused connection I can see this is possible, simply because a filtered connection that doesn't send a TCP RESET won't cause an error at the socket layer (it just won't connect). That leads to this hanging: >>> Pipeline( TCPClient("www.google.com", 8000), ConsoleEchoer() ).run() ... Which is (part of) why you're after timeouts etc, and go after that root cause. > Michael, I'm starting to think that this whole TTL component that I've > made might be completely unneeded. I think I was just reacting to the > bugs that I've been describing in other threads. If we could identify > why refused connections are infinite looping on vista and why > unconnected udp peers are refusing to shutdown, there might be no need > for this kind of time terminating component I agree that going after the root cause is a good idea. (That said, the TTL component is sufficiently generic to be useful beyond this issue, even if we deal with it differently) I think you're hitting a combination of things, in the main code, we have: while not self.safeConnect(sock,(self.host, self.port)): if self.shutdown(): return yield 1 This in combination with the other parts is probably why you're seeing a looping connect attempt. This goes into safeConnect, and if you're connecting to a filtered connection, it would hit this logic path in safeConnect: try: sock.connect(*sockArgsList); # Expect socket.error: (115, 'Operation now in progress') .... except socket.error, socket.msg: (errorno, errmsg) = socket.msg.args if errorno==errno.EALREADY: # The socket is non-blocking and a previous connection attempt has not yet been completed # We handle this by allowing the code to come back and repeatedly retry # connecting. This is a valid, if brute force approach. assert(self.connecting==1) return False elif errorno==errno.EINPROGRESS or errorno==errno.EWOULDBLOCK: #The socket is non-blocking and the connection cannot be completed immediately. # We handle this by allowing the code to come back and repeatedly retry # connecting. Rather brute force. self.connecting=1 return False # Not connected should retry until no error ie it hits one of these three conditions. For what it's worth a non-filtered not connected socket hits this path: try: sock.connect(*sockArgsList); # Expect socket.error: (115, 'Operation now in progress') .... except socket.error, socket.msg: (errorno, errmsg) = socket.msg.args if errorno==errno.EALREADY: .... # Anything else is an error we don't handle else: raise socket.msg That causes the socket cleanup, producerFinished to be sent out of signal and exit. Now there's several ways that I could go down this, but I can see that probably the simplest would be to add a connection timeout this way: class TCPClient(Axon.Component.component): def __init__(self,host,port,delay=0,connect_timeout=60): self.connect_timeout = connect_timeout ... connect_start = time.time() while not self.safeConnect(sock,(self.host, self.port)): if self.shutdown(): return if ( time.time() - connect_start ) > self.connect_timeout: self.howDied = "timeout" raise Finality yield 1 This by itself doesn't immediately resolve the "using CPU 100%" issue, but one thing at a time. Any thoughts welcome. In the meantime I'll experiment with this. Michael. -- http://yeoldeclue.com/blog http://twitter.com/kamaelian http://www.kamaelia.org/Home --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "kamaelia" group. To post to this group, send email to kamaelia@googlegroups.com To unsubscribe from this group, send email to kamaelia+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/kamaelia?hl=en -~----------~----~----~----~------~----~------~--~---