On Wednesday 01 April 2009 10:06:02 Michael Sparks wrote:
...
> I'll ensure that I merge the patches onto a branch tonight for review and
> merge (unless someone else offers to do so first).

OK, I've collated the TCP related bug fixes into a single branch here:
/branches/private_TB_TCPFixes20090316

ie
http://code.google.com/p/kamaelia/source/browse/branches/private_TB_TCPFixes20090316/
http://kamaelia.googlecode.com/svn/branches/private_TB_TCPFixes20090316

I've made a handful of minor changes to this branch, and made a few comments
for future work. The resulting patch is also attached to this mail for
information/feedback/suggestion. Your mail format / summary though
was really helpful BTW :-)

In order to merge this - at present - I need to have your explicit permission
to distribute these changes under both a BSD license (or Apache 2 license)
and also the existing Kamaelia license. (means that the GPL/LGPL/MPL
on the library originates from a single entity)

Which is what this contributor agreement boils down to:
   * http://www.kamaelia.org/Developers/SampleContributorAgreement

(That's a little heavyweight though - just confirmation is fine :-)

Please note that it is my intent to change the Kamaelia license over to the 
Apache License -- as per here:
   * http://www.apache.org/licenses/LICENSE-2.0.html

The reason for this suggested change is to simplify saying "thank you" for 
contributions like this ! :)

Since as well as being BSD like (and hence playing nicely with other python 
libraries), it also has an implicit contributor clause simplifying the whole 
thing. (section 5 is really rather nifty)

Finally, many thanks for submitting these patches. If you're happy with
the issue above, I've very much appreciate being able to merge them
onto /trunk. (The minor issues I've noted in the branch can be dealt with 
later - code is never perfect, and in this case merging now is better than 
never :)

Regards,


Michael (now off to create a branch for the UDP related fixes)
-- 
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 [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/kamaelia?hl=en
-~----------~----~----~----~------~----~------~--~---

Index: Kamaelia/Kamaelia/Internet/TCPServer.py
===================================================================
--- Kamaelia/Kamaelia/Internet/TCPServer.py	(revision 6069)
+++ Kamaelia/Kamaelia/Internet/TCPServer.py	(revision 6073)
@@ -91,7 +91,7 @@
 from Kamaelia.IPC import newReader, newWriter
 from Kamaelia.IPC import removeReader, removeWriter
 from Kamaelia.IPC import serverShutdown
-from Axon.Ipc import shutdown
+from Axon.Ipc import shutdown, shutdownMicroprocess
 
 class TCPServer(Axon.Component.component):
    """\
@@ -141,8 +141,22 @@
           s.setsockopt(*self.socketOptions)
       s.setblocking(0)
       assert self.debugger.note("PrimaryListenSocket.makeTCPServerPort", 5, "HOST,PORT",":",HOST,":",PORT,":")
-      s.bind((HOST,PORT))
-      s.listen(maxlisten)
+      try:
+          s.bind((HOST,PORT))
+          s.listen(maxlisten)
+      except socket.error:
+          return None, None # FIXME: Later versions should potentially consider raising an exception here
+                            # FIXME: and failing primarily because this is failing silently - which is
+                            # FIXME: probably a BAD thing. cf Zen of Python:
+                            # FIXME:          Errors should never pass silently.
+                            # FIXME: 
+                            # FIXME: We are of course doing this:
+                            # FIXME:      Unless explicitly silenced.
+                            # FIXME: 
+                            # FIXME: But in practice this is probably a bad idea in this case in this way. Really requires
+                            # FIXME: a change to ConnectedServer.ServerCore ...
+                            # FIXME: That said, "main" below resolves this by passing on the fact that the server socket
+                            # FIXME: doesn't exist and shuts down.
       return s,PORT
 
    def createConnectedSocket(self, sock):
@@ -227,6 +241,13 @@
 #             return CSA
 
    def main(self):
+       if self.listener is None:
+           self.send(shutdownMicroprocess, 'signal') # FIXME: Should probably be producerFinished. 
+                                                     # FIXME: (ie advisory that I've finished, rather than
+                                                     # FIXME: demand next component to shutdown)
+           yield 1
+           return  # NOTE: Change from suggested fix. (Simplifies code logic/makes diff smaller)
+
        selectorService, selectorShutdownService, newSelector = Selector.getSelectorServices(self.tracker)
        if newSelector:
            newSelector.activate()
@@ -249,15 +270,15 @@
                    break
            yield 1
        self.send(removeReader(self, self.listener), "_selectorSignal") 
-#       for i in xrange(100): yield 1
        self.send(shutdown(), "_selectorShutdownSignal")
 
    def stop(self):
-       self.send(removeReader(self, self.listener), "_selectorSignal") 
-#       for i in xrange(100): yield 1
-       self.send(shutdown(), "_selectorShutdownSignal")
-       self.listener.close() # Ensure we close the server socket. Only really likely to
-                             # be called from the scheduler shutting down due to a stop.
+       if self.listener is not None:
+           self.send(removeReader(self, self.listener), "_selectorSignal") 
+           self.send(shutdown(), "_selectorShutdownSignal")
+           self.listener.close() # Ensure we close the server socket. Only really likely to
+                                 # be called from the scheduler shutting down due to a stop.
+           self.listener = None
        super(TCPServer,self).stop()
 
 
Index: Kamaelia/Kamaelia/Internet/Selector.py
===================================================================
--- Kamaelia/Kamaelia/Internet/Selector.py	(revision 6069)
+++ Kamaelia/Kamaelia/Internet/Selector.py	(revision 6073)
@@ -74,10 +74,10 @@
 Register for a notification by sending an one of the following messages to the
 "notify" inbox, as returned by Selector.getSelectorService():
 
-* Kamaelia.KamaeliaIpc.newReader( (component,inboxname), descriptor)
-* Kamaelia.KamaeliaIpc.newWriter( (component,inboxname), descriptor)
-* Kamaelia.KamaeliaIpc.newExceptional( (component,inboxname), descriptor)
-   
+* Kamaelia.KamaeliaIpc.newReader(caller, (component,inboxname), descriptor)
+* Kamaelia.KamaeliaIpc.newWriter(caller, (component,inboxname), descriptor)
+* Kamaelia.KamaeliaIpc.newExceptional(caller, (component,inboxname), descriptor)
+
 Choose which as appropriate:
 
 * a newReader() request will notify when there is data ready to be read on
@@ -102,9 +102,9 @@
 Deregister by sending on of the following messages to the "notify" inbox of
 Selector:
 
-* Kamaelia.KamaeliaIpc.removeReader( (component,inboxname), descriptor)
-* Kamaelia.KamaeliaIpc.removeWriter( (component,inboxname), descriptor)
-* Kamaelia.KamaeliaIpc.removeExceptional( (component,inboxname), descriptor)
+* Kamaelia.KamaeliaIpc.removeReader(caller, descriptor)
+* Kamaelia.KamaeliaIpc.removeWriter(caller, descriptor)
+* Kamaelia.KamaeliaIpc.removeExceptional(caller, descriptor)
 
 It is advisable to send a deregister message when the corresponding file
 descriptor closes, in case you registered for a notification, but it has not
Index: Kamaelia/Kamaelia/Internet/TCPClient.py
===================================================================
--- Kamaelia/Kamaelia/Internet/TCPClient.py	(revision 6069)
+++ Kamaelia/Kamaelia/Internet/TCPClient.py	(revision 6073)
@@ -156,9 +156,8 @@
       """Main loop."""
 
       # wait before connecting
-      import time
-      t=time.time()
-      while time.time()-t<self.delay:
+      waitUntil = time.time() + self.delay
+      while time.time() < waitUntil:
          yield 1
 
       for v in self.runClient():
@@ -237,8 +236,15 @@
             #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
+            if not getattr(self, 'connecting', 0):
+                self.connecting=1
+                return False # Not connected should retry until no error
+            else:
+                # MSW doesn't raise a nice connection refused exception.  Instead
+                # we detect going from a WSAEINVAL (like EALREADY for windows) back to a
+                # EWOULDBLOCK which means the connection was refused and we are trying to
+                # connect for a second time.
+                raise errno.ECONNREFUSED
          elif errorno == errno.EISCONN:
              # This is a windows error indicating the connection has already been made.
              self.connecting = 0 # as with the no exception case.
@@ -249,6 +255,8 @@
                 # above.
                 assert(self.connecting==1)
                 return False
+            else:
+                raise socket.msg # We're on windows platform and unk exception occurred
          # Anything else is an error we don't handle
          else:
             raise socket.msg
@@ -262,11 +270,11 @@
          try:
             sock.setblocking(0); yield 0.6
             try:
-               startConnect = time.time()
+               tryUntil = time.time() + self.connect_timeout
                while not self.safeConnect(sock,(self.host, self.port)):
                   if self.shutdown():
                       return
-                  if ( time.time() - startConnect ) > self.connect_timeout:
+                  if time.time() >= tryUntil:
                       self.howDied = "timeout"
                       raise Finality
                   yield 1

Reply via email to