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