From 15ac3e9fba8fe63b4de64564533d7269def9041e Mon Sep 17 00:00:00 2001
From: Tom Nichols <tmnichols@gmail.com>
Date: Mon, 28 Jun 2010 11:06:26 -0400
Subject: race condition where we were transitioning to 'disconnected' and
 immediately reconnecting in another thread before the socket.close call
 occurred.  Now we're locking the state machine until the disconnect routine
 completes.

---
 sleekxmpp/xmlstream/xmlstream.py | 39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/sleekxmpp/xmlstream/xmlstream.py b/sleekxmpp/xmlstream/xmlstream.py
index 6dbe7b30..b669a31d 100644
--- a/sleekxmpp/xmlstream/xmlstream.py
+++ b/sleekxmpp/xmlstream/xmlstream.py
@@ -59,7 +59,7 @@ class XMLStream(object):
 		self.ssl_support = ssl_support
 		self.escape_quotes = escape_quotes
 		self.state = statemachine.StateMachine(('disconnected','connecting',
-		    'connected'))
+			'connected'))
 		self.should_reconnect = True
 
 		self.setSocket(socket)
@@ -240,7 +240,7 @@ class XMLStream(object):
 				if self.should_reconnect:
 					self.disconnect(reconnect=True)
 
-        logging.debug('Quitting Process thread')
+		logging.debug('Quitting Process thread')
 	
 	def __readXML(self):
 		"Parses the incoming stream, adding to xmlin queue as it goes"
@@ -302,23 +302,24 @@ class XMLStream(object):
 		return True
 	
 	def disconnect(self, reconnect=False):
-		if not self.state.transition('connected','disconnected'):
-			logging.warning("Already disconnected.")
-			return
-		logging.debug("Disconnecting...")
-		self.sendRaw(self.stream_footer)
-		time.sleep(5)
-		#send end of stream
-		#wait for end of stream back
-		try:
-#			self.socket.shutdown(socket.SHUT_RDWR)
-			self.socket.close()
-		except socket.error as (errno,strerror):
-			logging.exception("Error while disconnecting. Socket Error #%s: %s" % (errno, strerror))		
-		try:
-			self.filesocket.close()
-		except socket.error as (errno,strerror):
-			logging.exception("Error closing filesocket.")
+		with self.state.transition_ctx('connected','disconnected') as locked:
+			if not locked:
+				logging.warning("Already disconnected.")
+				return
+			logging.debug("Disconnecting...")
+			self.sendRaw(self.stream_footer)
+			time.sleep(5)
+			#send end of stream
+			#wait for end of stream back
+			try:
+#				self.socket.shutdown(socket.SHUT_RDWR)
+				self.socket.close()
+			except socket.error as (errno,strerror):
+				logging.exception("Error while disconnecting. Socket Error #%s: %s" % (errno, strerror))
+			try:
+				self.filesocket.close()
+			except socket.error as (errno,strerror):
+				logging.exception("Error closing filesocket.")
 
 		if reconnect: self.connect()
 	
-- 
cgit v1.2.3