Commit c4fcba3a authored by Amos Latteier's avatar Amos Latteier

Added a lock to tempfile producers. Thanks to Toby Dickenson. This should...

Added a lock to tempfile producers. Thanks to Toby Dickenson. This should avoid possible corruption of responses from FCGI and large HTTP responses.
parent 1dd29bd5
......@@ -117,6 +117,7 @@ from cStringIO import StringIO
from tempfile import TemporaryFile
import socket, string, os, sys, time
from types import StringType
import thread
tz_for_log = compute_timezone_for_log()
......@@ -716,6 +717,7 @@ class FCGIServer(asyncore.dispatcher):
class FCGIResponse(HTTPResponse):
_tempfile=None
_templock=None
_tempstart=0
def setChannel(self, channel):
......@@ -731,6 +733,7 @@ class FCGIResponse(HTTPResponse):
if type(l) is type(''): l=string.atoi(l)
if l > 128000:
self._tempfile=TemporaryFile()
self._templock=thread.allocate_lock()
except: pass
stdout.write(str(self))
......@@ -750,10 +753,14 @@ class FCGIResponse(HTTPResponse):
l=len(chunk)
b=self._tempstart
e=b+l
t.seek(b)
t.write(chunk)
self._templock.acquire()
try:
t.seek(b)
t.write(chunk)
finally:
self._templock.release()
self._tempstart=e
stdout.write((file_part_producer(t,b,e), l))
stdout.write((file_part_producer(t,self._templock,b,e), l))
def _finish(self):
self.channel.reply_code=self.status
......
......@@ -91,7 +91,7 @@ and logging duties.
"""
import time, regex, string, sys, tempfile
from cStringIO import StringIO
import thread
from ZPublisher.HTTPResponse import HTTPResponse, end_of_header_search
from medusa.http_date import build_http_date
from PubCore.ZEvent import Wakeup
......@@ -215,7 +215,9 @@ class ZServerHTTPResponse(HTTPResponse):
return string.join(headersl,'\r\n')
_tempfile=None
_templock=None
_tempstart=0
def write(self,data):
"""\
Return data as a stream
......@@ -240,6 +242,7 @@ class ZServerHTTPResponse(HTTPResponse):
if type(l) is type(''): l=string.atoi(l)
if l > 128000:
self._tempfile=tempfile.TemporaryFile()
self._templock=thread.allocate_lock()
except: pass
stdout.write(str(self))
......@@ -254,10 +257,14 @@ class ZServerHTTPResponse(HTTPResponse):
l=len(data)
b=self._tempstart
e=b+l
t.seek(b)
t.write(data)
self._templock.acquire()
try:
t.seek(b)
t.write(data)
finally:
self._templock.release()
self._tempstart=e
stdout.write(file_part_producer(t,b,e), l)
stdout.write(file_part_producer(t,self._templock,b,e), l)
def _finish(self):
stdout=self.stdout
......
......@@ -128,8 +128,9 @@ class file_part_producer:
# match http_channel's outgoing buffer size
out_buffer_size = 1<<16
def __init__(self, file, start, end):
def __init__(self, file, lock, start, end):
self.file=file
self.lock=lock
self.start=start
self.end=end
......@@ -140,12 +141,17 @@ class file_part_producer:
if start >= end: return ''
file=self.file
file.seek(start)
size=end-start
bsize=self.out_buffer_size
if size > bsize: size=bsize
data = file.read(size)
self.lock.acquire()
try:
file.seek(start)
data = file.read(size)
finally:
self.lock.release()
if data:
start=start+len(data)
if start < end:
......
......@@ -117,6 +117,7 @@ from cStringIO import StringIO
from tempfile import TemporaryFile
import socket, string, os, sys, time
from types import StringType
import thread
tz_for_log = compute_timezone_for_log()
......@@ -716,6 +717,7 @@ class FCGIServer(asyncore.dispatcher):
class FCGIResponse(HTTPResponse):
_tempfile=None
_templock=None
_tempstart=0
def setChannel(self, channel):
......@@ -731,6 +733,7 @@ class FCGIResponse(HTTPResponse):
if type(l) is type(''): l=string.atoi(l)
if l > 128000:
self._tempfile=TemporaryFile()
self._templock=thread.allocate_lock()
except: pass
stdout.write(str(self))
......@@ -750,10 +753,14 @@ class FCGIResponse(HTTPResponse):
l=len(chunk)
b=self._tempstart
e=b+l
t.seek(b)
t.write(chunk)
self._templock.acquire()
try:
t.seek(b)
t.write(chunk)
finally:
self._templock.release()
self._tempstart=e
stdout.write((file_part_producer(t,b,e), l))
stdout.write((file_part_producer(t,self._templock,b,e), l))
def _finish(self):
self.channel.reply_code=self.status
......
......@@ -91,7 +91,7 @@ and logging duties.
"""
import time, regex, string, sys, tempfile
from cStringIO import StringIO
import thread
from ZPublisher.HTTPResponse import HTTPResponse, end_of_header_search
from medusa.http_date import build_http_date
from PubCore.ZEvent import Wakeup
......@@ -215,7 +215,9 @@ class ZServerHTTPResponse(HTTPResponse):
return string.join(headersl,'\r\n')
_tempfile=None
_templock=None
_tempstart=0
def write(self,data):
"""\
Return data as a stream
......@@ -240,6 +242,7 @@ class ZServerHTTPResponse(HTTPResponse):
if type(l) is type(''): l=string.atoi(l)
if l > 128000:
self._tempfile=tempfile.TemporaryFile()
self._templock=thread.allocate_lock()
except: pass
stdout.write(str(self))
......@@ -254,10 +257,14 @@ class ZServerHTTPResponse(HTTPResponse):
l=len(data)
b=self._tempstart
e=b+l
t.seek(b)
t.write(data)
self._templock.acquire()
try:
t.seek(b)
t.write(data)
finally:
self._templock.release()
self._tempstart=e
stdout.write(file_part_producer(t,b,e), l)
stdout.write(file_part_producer(t,self._templock,b,e), l)
def _finish(self):
stdout=self.stdout
......
......@@ -128,8 +128,9 @@ class file_part_producer:
# match http_channel's outgoing buffer size
out_buffer_size = 1<<16
def __init__(self, file, start, end):
def __init__(self, file, lock, start, end):
self.file=file
self.lock=lock
self.start=start
self.end=end
......@@ -140,12 +141,17 @@ class file_part_producer:
if start >= end: return ''
file=self.file
file.seek(start)
size=end-start
bsize=self.out_buffer_size
if size > bsize: size=bsize
data = file.read(size)
self.lock.acquire()
try:
file.seek(start)
data = file.read(size)
finally:
self.lock.release()
if data:
start=start+len(data)
if start < end:
......
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