You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by kw...@apache.org on 2015/04/03 17:51:57 UTC
svn commit: r1671094 - in /qpid/trunk/qpid/python/qpid: client.py
connection08.py peer.py
Author: kwall
Date: Fri Apr 3 15:51:57 2015
New Revision: 1671094
URL: http://svn.apache.org/r1671094
Log:
QPID-6474: [Python Client] Prevent client connection thread leaks on the 08..09 code path
Modified:
qpid/trunk/qpid/python/qpid/client.py
qpid/trunk/qpid/python/qpid/connection08.py
qpid/trunk/qpid/python/qpid/peer.py
Modified: qpid/trunk/qpid/python/qpid/client.py
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/python/qpid/client.py?rev=1671094&r1=1671093&r2=1671094&view=diff
==============================================================================
--- qpid/trunk/qpid/python/qpid/client.py (original)
+++ qpid/trunk/qpid/python/qpid/client.py Fri Apr 3 15:51:57 2015
@@ -126,7 +126,8 @@ class Client:
return self.channel(id)
def close(self):
- self.socket.close()
+ if self.peer:
+ self.peer.stop()
class ClientDelegate(Delegate):
Modified: qpid/trunk/qpid/python/qpid/connection08.py
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/python/qpid/connection08.py?rev=1671094&r1=1671093&r2=1671094&view=diff
==============================================================================
--- qpid/trunk/qpid/python/qpid/connection08.py (original)
+++ qpid/trunk/qpid/python/qpid/connection08.py Fri Apr 3 15:51:57 2015
@@ -118,6 +118,7 @@ class Connection:
self.FRAME_END = self.spec.constants.byname["frame_end"].id
self.write = getattr(self, "write_%s_%s" % (self.spec.major, self.spec.minor))
self.read = getattr(self, "read_%s_%s" % (self.spec.major, self.spec.minor))
+ self.io = io
def flush(self):
self.codec.flush()
@@ -250,6 +251,9 @@ class Connection:
def read_99_0(self):
return self.read_0_10()
+ def close(self):
+ self.io.close();
+
class Frame:
DECODERS = {}
Modified: qpid/trunk/qpid/python/qpid/peer.py
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/python/qpid/peer.py?rev=1671094&r1=1671093&r2=1671094&view=diff
==============================================================================
--- qpid/trunk/qpid/python/qpid/peer.py (original)
+++ qpid/trunk/qpid/python/qpid/peer.py Fri Apr 3 15:51:57 2015
@@ -24,7 +24,7 @@ sorts incoming frames to their intended
incoming method frames to a delegate.
"""
-import thread, threading, traceback, socket, sys, logging
+import threading, traceback, socket, sys
from connection08 import EOF, Method, Header, Body, Request, Response, VersionError
from message import Message
from queue import Queue, Closed as QueueClosed
@@ -32,6 +32,9 @@ from content import Content
from cStringIO import StringIO
from time import time
from exceptions import Closed
+from logging import getLogger
+
+log = getLogger("qpid.peer")
class Sequence:
@@ -39,7 +42,7 @@ class Sequence:
# we should keep start for wrap around
self._next = start
self.step = step
- self.lock = thread.allocate_lock()
+ self.lock = threading.Lock()
def next(self):
self.lock.acquire()
@@ -58,7 +61,7 @@ class Peer:
self.outgoing = Queue(0)
self.work = Queue(0)
self.channels = {}
- self.lock = thread.allocate_lock()
+ self.lock = threading.Lock()
if channel_factory:
self.channel_factory = channel_factory
else:
@@ -77,13 +80,20 @@ class Peer:
return ch
def start(self):
- thread.start_new_thread(self.writer, ())
- thread.start_new_thread(self.reader, ())
- thread.start_new_thread(self.worker, ())
+ self.writer_thread = threading.Thread(target=self.writer)
+ self.writer_thread.daemon = True
+ self.writer_thread.start()
+
+ self.reader_thread = threading.Thread(target=self.reader)
+ self.reader_thread.daemon = True
+ self.reader_thread.start()
+
+ self.worker_thread = threading.Thread(target=self.worker)
+ self.worker_thread.daemon = True
+ self.worker_thread.start()
def fatal(self, message=None):
"""Call when an unexpected exception occurs that will kill a thread."""
- if message: print >> sys.stderr, message
self.closed("Fatal error: %s\n%s" % (message or "", traceback.format_exc()))
def reader(self):
@@ -119,6 +129,8 @@ class Peer:
self.closed(e)
break
self.conn.flush()
+ except QueueClosed:
+ pass
except:
self.fatal()
@@ -139,6 +151,23 @@ class Peer:
except:
self.fatal()
+ def stop(self):
+ try:
+ self.work.close();
+ self.outgoing.close();
+ self.conn.close();
+ finally:
+ timeout = 1;
+ self.worker_thread.join(timeout);
+ if self.worker_thread.isAlive():
+ log.warn("Worker thread failed to shutdown within timeout")
+ self.reader_thread.join(timeout);
+ if self.reader_thread.isAlive():
+ log.warn("Reader thread failed to shutdown within timeout")
+ self.writer_thread.join(timeout);
+ if self.writer_thread.isAlive():
+ log.warn("Writer thread failed to shutdown within timeout")
+
class Requester:
def __init__(self, writer):
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org