Commit 5cb9e16e authored by Amos Latteier's avatar Amos Latteier

Fixed more potential leakage which could occur when channels were closed...

Fixed more potential leakage which could occur when channels were closed before the response was sent back.
parent 5845a0b9
......@@ -288,26 +288,29 @@ class ChannelPipe:
self._bytes=0
def write(self, text, l=None):
if self._channel.closed:
return
if l is None: l=len(text)
self._bytes=self._bytes + l
self._channel.push(text,0)
Wakeup()
def close(self):
DebugLogger.log('A', id(self._request),
'%s %s' % (self._request.reply_code, self._bytes))
self._channel.push(LoggingProducer(self._request, self._bytes), 0)
self._channel.push(CallbackProducer(self._channel.done), 0)
self._channel.push(CallbackProducer(
lambda t=('E', id(self._request)): apply(DebugLogger.log, t)), 0)
if self._shutdown:
try: r=self._shutdown[0]
except: r=0
sys.ZServerExitCode=r
self._channel.push(ShutdownProducer(), 0)
Wakeup(lambda: asyncore.close_all())
else:
if self._close: self._channel.push(None, 0)
if not self._channel.closed:
DebugLogger.log('A', id(self._request),
'%s %s' % (self._request.reply_code, self._bytes))
self._channel.push(LoggingProducer(self._request, self._bytes), 0)
self._channel.push(CallbackProducer(self._channel.done), 0)
self._channel.push(CallbackProducer(
lambda t=('E', id(self._request)): apply(DebugLogger.log, t)), 0)
if self._shutdown:
try: r=self._shutdown[0]
except: r=0
sys.ZServerExitCode=r
self._channel.push(ShutdownProducer(), 0)
Wakeup(lambda: asyncore.close_all())
else:
if self._close: self._channel.push(None, 0)
Wakeup()
self._channel=None #need to break cycles?
......
......@@ -119,7 +119,7 @@ from ZPublisher.HTTPRequest import HTTPRequest
from medusa.http_server import http_server, http_channel
from medusa import counter, producers, asyncore, max_sockets
from medusa.default_handler import split_path, unquote, get_header
from medusa.asyncore import compact_traceback
from medusa.asyncore import compact_traceback, dispatcher
from ZServer import CONNECTION_LIMIT, ZOPE_VERSION, ZSERVER_VERSION
......@@ -314,6 +314,8 @@ class zhttp_handler:
class zhttp_channel(http_channel):
"http channel"
closed=0
def __init__(self, server, conn, addr):
http_channel.__init__(self, server, conn, addr)
......@@ -324,6 +326,8 @@ class zhttp_channel(http_channel):
# this is thread-safe when send is false
# note, that strings are not wrapped in
# producers by default
if self.closed:
return
self.producer_fifo.push(producer)
if send: self.initiate_send()
......@@ -338,33 +342,37 @@ class zhttp_channel(http_channel):
except: return
handle(module_name, request, response)
def handle_close(self):
def close(self):
self.closed=1
while self.queue:
self.queue.pop()
if self.current_request is not None:
self.current_request.channel=None # break circ refs
self.current_request=None
while self.producer_fifo:
self.producer_fifo.pop()
self.close()
def handle_error (self):
(file,fun,line), t, v, tbinfo = compact_traceback()
# sometimes a user repr method will crash.
try:
self_repr = repr (self)
except:
self_repr = '<__repr__ (self) failed for object at %0x>' % id(self)
self.log_info (
'uncaptured python exception, closing channel %s (%s:%s %s)' % (
self_repr,
t,
v,
tbinfo
),
'error'
)
self.handle_close()
p=self.producer_fifo.pop()
p.more()
dispatcher.close(self)
# def handle_error (self):
# (file,fun,line), t, v, tbinfo = compact_traceback()
#
# # sometimes a user repr method will crash.
# try:
# self_repr = repr (self)
# except:
# self_repr = '<__repr__ (self) failed for object at %0x>' % id(self)
#
# self.log_info (
# 'uncaptured python exception, closing channel %s (%s:%s %s)' % (
# self_repr,
# t,
# v,
# tbinfo
# ),
# 'error'
# )
# self.handle_close()
def done(self):
"Called when a publishing request is finished"
......
......@@ -106,6 +106,7 @@ class LoggingProducer:
def more(self):
getattr(self.logger, self.method)(self.bytes)
self.logger=None
return ''
......@@ -117,5 +118,6 @@ class CallbackProducer:
def more(self):
self.callback()
self.callback=None
return ''
\ No newline at end of file
......@@ -288,26 +288,29 @@ class ChannelPipe:
self._bytes=0
def write(self, text, l=None):
if self._channel.closed:
return
if l is None: l=len(text)
self._bytes=self._bytes + l
self._channel.push(text,0)
Wakeup()
def close(self):
DebugLogger.log('A', id(self._request),
'%s %s' % (self._request.reply_code, self._bytes))
self._channel.push(LoggingProducer(self._request, self._bytes), 0)
self._channel.push(CallbackProducer(self._channel.done), 0)
self._channel.push(CallbackProducer(
lambda t=('E', id(self._request)): apply(DebugLogger.log, t)), 0)
if self._shutdown:
try: r=self._shutdown[0]
except: r=0
sys.ZServerExitCode=r
self._channel.push(ShutdownProducer(), 0)
Wakeup(lambda: asyncore.close_all())
else:
if self._close: self._channel.push(None, 0)
if not self._channel.closed:
DebugLogger.log('A', id(self._request),
'%s %s' % (self._request.reply_code, self._bytes))
self._channel.push(LoggingProducer(self._request, self._bytes), 0)
self._channel.push(CallbackProducer(self._channel.done), 0)
self._channel.push(CallbackProducer(
lambda t=('E', id(self._request)): apply(DebugLogger.log, t)), 0)
if self._shutdown:
try: r=self._shutdown[0]
except: r=0
sys.ZServerExitCode=r
self._channel.push(ShutdownProducer(), 0)
Wakeup(lambda: asyncore.close_all())
else:
if self._close: self._channel.push(None, 0)
Wakeup()
self._channel=None #need to break cycles?
......
......@@ -119,7 +119,7 @@ from ZPublisher.HTTPRequest import HTTPRequest
from medusa.http_server import http_server, http_channel
from medusa import counter, producers, asyncore, max_sockets
from medusa.default_handler import split_path, unquote, get_header
from medusa.asyncore import compact_traceback
from medusa.asyncore import compact_traceback, dispatcher
from ZServer import CONNECTION_LIMIT, ZOPE_VERSION, ZSERVER_VERSION
......@@ -314,6 +314,8 @@ class zhttp_handler:
class zhttp_channel(http_channel):
"http channel"
closed=0
def __init__(self, server, conn, addr):
http_channel.__init__(self, server, conn, addr)
......@@ -324,6 +326,8 @@ class zhttp_channel(http_channel):
# this is thread-safe when send is false
# note, that strings are not wrapped in
# producers by default
if self.closed:
return
self.producer_fifo.push(producer)
if send: self.initiate_send()
......@@ -338,33 +342,37 @@ class zhttp_channel(http_channel):
except: return
handle(module_name, request, response)
def handle_close(self):
def close(self):
self.closed=1
while self.queue:
self.queue.pop()
if self.current_request is not None:
self.current_request.channel=None # break circ refs
self.current_request=None
while self.producer_fifo:
self.producer_fifo.pop()
self.close()
def handle_error (self):
(file,fun,line), t, v, tbinfo = compact_traceback()
# sometimes a user repr method will crash.
try:
self_repr = repr (self)
except:
self_repr = '<__repr__ (self) failed for object at %0x>' % id(self)
self.log_info (
'uncaptured python exception, closing channel %s (%s:%s %s)' % (
self_repr,
t,
v,
tbinfo
),
'error'
)
self.handle_close()
p=self.producer_fifo.pop()
p.more()
dispatcher.close(self)
# def handle_error (self):
# (file,fun,line), t, v, tbinfo = compact_traceback()
#
# # sometimes a user repr method will crash.
# try:
# self_repr = repr (self)
# except:
# self_repr = '<__repr__ (self) failed for object at %0x>' % id(self)
#
# self.log_info (
# 'uncaptured python exception, closing channel %s (%s:%s %s)' % (
# self_repr,
# t,
# v,
# tbinfo
# ),
# 'error'
# )
# self.handle_close()
def done(self):
"Called when a publishing request is finished"
......
......@@ -106,6 +106,7 @@ class LoggingProducer:
def more(self):
getattr(self.logger, self.method)(self.bytes)
self.logger=None
return ''
......@@ -117,5 +118,6 @@ class CallbackProducer:
def more(self):
self.callback()
self.callback=None
return ''
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment