#1183 closed enhancement (fixed)
[PATCH] Handle disconnecting tracd clients more gracefully.
Reported by: | Owned by: | Christian Boos | |
---|---|---|---|
Priority: | high | Milestone: | 0.11.5 |
Component: | web frontend/tracd | Version: | 0.8 |
Severity: | normal | Keywords: | python23 |
Cc: | Branch: | ||
Release Notes: | |||
API Changes: | |||
Internal Changes: |
Description
Currently, when a client disconnects unexpectedly, tracd
prints a needlessly verbose traceback:
---------------------------------------- Exception happened during processing of request from ('1.2.3.4', 5678) Traceback (most recent call last): File "/usr/local/lib/python2.4/SocketServer.py", line 463, in process_request_thread self.finish_request(request, client_address) File "/usr/local/lib/python2.4/SocketServer.py", line 254, in finish_request self.RequestHandlerClass(request, client_address, self) File "/usr/local/lib/python2.4/SocketServer.py", line 521, in __init__ self.handle() File "/usr/local/lib/python2.4/BaseHTTPServer.py", line 314, in handle self.handle_one_request() File "/usr/local/lib/python2.4/BaseHTTPServer.py", line 308, in handle_one_request method() File "/usr/local/bin/tracd", line 227, in do_GET self.do_trac_req() File "/usr/local/bin/tracd", line 238, in do_trac_req trac.core.send_pretty_error(e, self.env, self) File "/usr/local/lib/python2.4/site-packages/trac/core.py", line 494, in send_pretty_error req.send_response(500) File "/usr/local/lib/python2.4/BaseHTTPServer.py", line 364, in send_response self.wfile.write("%s %d %s\r\n" % File "/usr/local/lib/python2.4/socket.py", line 256, in write self.flush() File "/usr/local/lib/python2.4/socket.py", line 243, in flush self._sock.sendall(buffer) error: (32, 'Broken pipe') ----------------------------------------
With the following patch, tracd
will log a short message instead, which is about all one can do in this situation.
--- tracd.orig Tue Jan 18 13:26:40 2005 +++ tracd Thu Feb 3 12:03:30 2005 @@ -32,6 +32,7 @@ import shutil import getopt import locale +import socket, errno import urllib import urllib2 import mimetypes @@ -235,7 +236,14 @@ try: self.do_real_trac_req() except Exception, e: - trac.core.send_pretty_error(e, self.env, self) + try: + trac.core.send_pretty_error(e, self.env, self) + except socket.error, (code, msg): + if code == errno.EPIPE: + self.log_message('Lost connection to client: %s', self.address_string()) + else: + raise def do_real_trac_req(self): start = time.time()
Attachments (1)
Change History (16)
comment:1 by , 20 years ago
comment:2 by , 20 years ago
This one is even better at removing spurious stack traces, and works also on Windows.
It also fixes the long standing 'Conten-Length'
misspelling!
-
trac/web/standalone.py
33 33 import sys 34 34 import md5 35 35 import time 36 import socket, errno 36 37 import shutil 37 38 import urllib 38 39 import urllib2 … … 192 193 except IOError: 193 194 self.send_error(404, path) 194 195 return 195 self.send_response(200) 196 mtype, enc = mimetypes.guess_type(filename) 197 stat = os.fstat(f.fileno()) 198 content_length = stat[6] 199 last_modified = time.strftime("%a, %d %b %Y %H:%M:%S GMT", 200 time.gmtime(stat[8])) 201 self.send_header('Content-Type', mtype) 202 self.send_header('Conten-Length', str(content_length)) 203 self.send_header('Last-Modified', last_modified) 204 self.end_headers() 205 shutil.copyfileobj(f, self.wfile) 206 196 try: 197 self.send_response(200) 198 mtype, enc = mimetypes.guess_type(filename) 199 stat = os.fstat(f.fileno()) 200 content_length = stat[6] 201 last_modified = time.strftime("%a, %d %b %Y %H:%M:%S GMT", 202 time.gmtime(stat[8])) 203 self.send_header('Content-Type', mtype) 204 self.send_header('Content-Length', str(content_length)) 205 self.send_header('Last-Modified', last_modified) 206 self.end_headers() 207 shutil.copyfileobj(f, self.wfile) 208 except socket.error, (code, msg): 209 if code == errno.EPIPE or code == 10053: # Windows 210 self.log_message('Lost connection to client: %s', self.address_string()) 211 else: 212 raise 213 207 214 def do_POST(self): 208 215 self.do_trac_req() 209 216 … … 245 252 start = time.time() 246 253 dispatch_request(path_info, req, env) 247 254 self.log.debug('Total request time: %f s', time.time() - start) 255 except socket.error, (code, msg): 256 if code == errno.EPIPE or code == 10053: # Windows 257 self.log_message('Lost connection to client: %s', self.address_string()) 258 else: 259 raise 248 260 except Exception, e: 249 send_pretty_error(e, env, req) 261 try: 262 send_pretty_error(e, env, req) 263 except socket.error, (code, msg): 264 if code == errno.EPIPE or code == 10053: # Windows 265 self.log_message('Lost connection to client: %s', self.address_string()) 266 else: 267 raise 250 268 251 269 252 270 class TracHTTPRequest(Request):
Should I commit it?
comment:3 by , 20 years ago
Owner: | changed from | to
---|
Sure. I was also wondering if this patch helped make tracd more stable for you in relation to #1401?
comment:4 by , 20 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:5 by , 18 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Was 0.9, but looks like the WSGI changes got rid of this…
Exception happened during processing of request from ('127.0.0.1', 2939) Traceback (most recent call last): File "C:\Program Files\ActiveState\Python-2.4\lib\SocketServer.py", line 463, in process_request_thread self.finish_request(request, client_address) File "C:\Program Files\ActiveState\Python-2.4\lib\SocketServer.py", line 254, in finish_request self.RequestHandlerClass(request, client_address, self) File "C:\Program Files\ActiveState\Python-2.4\lib\SocketServer.py", line 521, in __init__ self.handle() File "C:\Program Files\ActiveState\Python-2.4\lib\BaseHTTPServer.py", line 316, in handle self.handle_one_request() File "C:\Workspace\src\trac\branches\0.10-stable\trac\web\wsgi.py", line 174, in handle_one_request gateway.run(self.server.application) File "C:\Workspace\src\trac\branches\0.10-stable\trac\web\wsgi.py", line 95, in run self._write(chunk) File "C:\Workspace\src\trac\branches\0.10-stable\trac\web\wsgi.py", line 195, in _write self.handler.send_response(int(status[:3])) File "C:\Program Files\ActiveState\Python-2.4\lib\BaseHTTPServer.py", line 370, in send_response self.send_header('Server', self.version_string()) File "C:\Program Files\ActiveState\Python-2.4\lib\BaseHTTPServer.py", line 377, in send_header self.wfile.write("%s: %s\r\n" % (keyword, value)) File "C:\Program Files\ActiveState\Python-2.4\lib\socket.py", line 256, in write self.flush() File "C:\Program Files\ActiveState\Python-2.4\lib\socket.py", line 243, in flush 127.0.0.1 - - [08/Jan/2007 10:05:04] "GET /devel/timeline HTTP/1.1" 200 - self._sock.sendall(buffer) error: (10053, 'Software caused connection abort')
(the above with 0.10.4dev)
by , 18 years ago
Attachment: | trap_connection_interrupted-r4510.diff added |
---|
Reimplement silencing of connection interrupted errors in the request dispatcher
follow-up: 8 comment:6 by , 18 years ago
Keywords: | review added |
---|---|
Milestone: | → 0.10.4 |
Priority: | low → normal |
In attachment:trap_connection_interrupted-r4510.diff, I did this error catching in trac/web/main.py, as doing it in wsgi.py didn't work reliably.
Doing:
-
trac/web/wsgi.py
171 171 def handle_one_request(self): 172 172 environ = self.setup_environ() 173 173 gateway = self.server.gateway(self, environ) 174 gateway.run(self.server.application) 174 import errno, socket 175 try: 176 gateway.run(self.server.application) 177 except socket.error, (code, msg): 178 if code == errno.EPIPE or code == 10053: # Windows 179 pass 180 else: 181 raise 175 182 176 183 def finish(self): 177 184 """We need to help the garbage collector a little."""
didn't prevent the following kind of exception:
Traceback (most recent call last): File "C:\Workspace\src\trac\trunk\trac\web\main.py", line 395, in dispatch_request dispatcher.dispatch(req) File "C:\Workspace\src\trac\trunk\trac\web\main.py", line 231, in dispatch req.send(output, content_type or 'text/html') File "C:\Workspace\src\trac\trunk\trac\web\api.py", line 313, in send self.write(content) File "C:\Workspace\src\trac\trunk\trac\web\api.py", line 410, in write self._write(data) File "C:\Workspace\src\trac\trunk\trac\web\wsgi.py", line 202, in _write self.handler.send_response(int(status[:3])) File "C:\Program Files\ActiveState\Python-2.4\lib\BaseHTTPServer.py", line 370, in send_response self.send_header('Server', self.version_string()) File "C:\Program Files\ActiveState\Python-2.4\lib\BaseHTTPServer.py", line 377, in send_header self.wfile.write("%s: %s\r\n" % (keyword, value)) File "C:\Program Files\ActiveState\Python-2.4\lib\socket.py", line 256, in write self.flush() File "C:\Program Files\ActiveState\Python-2.4\lib\socket.py", line 243, in flush self._sock.sendall(buffer) error: (10053, 'Software caused connection abort')
By the way, while testing this patch, I've noticed it's quite easy to "saturate" tracd and have all the db connections in use; new requests are then blocking on the pool lock and after a while the timeout exception is raised. This is a separate issue, though, but easy to reproduce when you keep the "F5" key down ;)
comment:7 by , 18 years ago
Milestone: | 0.10.5 → 0.11 |
---|
comment:8 by , 17 years ago
Keywords: | review removed |
---|---|
Priority: | normal → high |
Replying to cboos:
… I've noticed it's quite easy to "saturate" tracd and have all the db connections in use; new requests are then blocking on the pool lock and after a while the timeout exception is raised. This is a separate issue, though, but easy to reproduce when you keep the "F5" key down ;)
r6261 seems to have fixed that.
comment:9 by , 16 years ago
Milestone: | 0.11-retriage → 0.11.5 |
---|
Move high prio tickets from 0.11-retriage to next maintenance release.
comment:10 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
Fixed in r8080. Before writing to the client, we first check if the file object is not already closed.
comment:11 by , 16 years ago
Keywords: | python23 added |
---|
Note that the fix doesn't work with Python 2.3 (see r8128).
comment:12 by , 16 years ago
Component: | web frontend/tracd → version control/log view |
---|
comment:13 by , 16 years ago
Component: | version control/log view → web frontend/tracd |
---|
Please stop messing with this server, thanks.
The patch below has been synced with trunk at r1502. It also handles the EPIPE that can occur during
dispatch_request
: