Show More
@@ -252,3 +252,6 b' class UnsupportedBundleSpecification(Exc' | |||
|
252 | 252 | |
|
253 | 253 | class CorruptedState(Exception): |
|
254 | 254 | """error raised when a command is not able to read its state from file""" |
|
255 | ||
|
256 | class RichIOError(Abort): | |
|
257 | """An IOError that can also have a hint attached.""" |
@@ -75,6 +75,41 b' def encodevalueinheaders(value, header, ' | |||
|
75 | 75 | |
|
76 | 76 | return result |
|
77 | 77 | |
|
78 | def _wraphttpresponse(resp): | |
|
79 | """Wrap an HTTPResponse with common error handlers. | |
|
80 | ||
|
81 | This ensures that any I/O from any consumer raises the appropriate | |
|
82 | error and messaging. | |
|
83 | """ | |
|
84 | origread = resp.read | |
|
85 | ||
|
86 | class readerproxy(resp.__class__): | |
|
87 | def read(self, size=None): | |
|
88 | try: | |
|
89 | return origread(size) | |
|
90 | except httplib.IncompleteRead as e: | |
|
91 | # e.expected is an integer if length known or None otherwise. | |
|
92 | if e.expected: | |
|
93 | msg = _('HTTP request error (incomplete response; ' | |
|
94 | 'expected %d bytes got %d)') % (e.expected, | |
|
95 | len(e.partial)) | |
|
96 | else: | |
|
97 | msg = _('HTTP request error (incomplete response)') | |
|
98 | ||
|
99 | raise error.RichIOError( | |
|
100 | msg, | |
|
101 | hint=_('this may be an intermittent network failure; ' | |
|
102 | 'if the error persists, consider contacting the ' | |
|
103 | 'network or server operator')) | |
|
104 | except httplib.HTTPException as e: | |
|
105 | raise error.RichIOError( | |
|
106 | _('HTTP request error (%s)') % e, | |
|
107 | hint=_('this may be an intermittent failure; ' | |
|
108 | 'if the error persists, consider contacting the ' | |
|
109 | 'network or server operator')) | |
|
110 | ||
|
111 | resp.__class__ = readerproxy | |
|
112 | ||
|
78 | 113 | class httppeer(wireproto.wirepeer): |
|
79 | 114 | def __init__(self, ui, path): |
|
80 | 115 | self.path = path |
@@ -223,6 +258,10 b' class httppeer(wireproto.wirepeer):' | |||
|
223 | 258 | self.ui.debug('http error while sending %s command\n' % cmd) |
|
224 | 259 | self.ui.traceback() |
|
225 | 260 | raise IOError(None, inst) |
|
261 | ||
|
262 | # Insert error handlers for common I/O failures. | |
|
263 | _wraphttpresponse(resp) | |
|
264 | ||
|
226 | 265 | # record the url we got redirected to |
|
227 | 266 | resp_url = resp.geturl() |
|
228 | 267 | if resp_url.endswith(qs): |
@@ -267,10 +267,10 b' Server sends an incomplete capabilities ' | |||
|
267 | 267 | $ hg --config badserver.closeaftersendbytes=180 serve -p $HGPORT -d --pid-file=hg.pid -E error.log |
|
268 | 268 | $ cat hg.pid > $DAEMON_PIDS |
|
269 | 269 | |
|
270 | TODO client spews a stack due to uncaught httplib.IncompleteRead | |
|
271 | ||
|
272 | $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null | |
|
273 |
[ |
|
|
270 | $ hg clone http://localhost:$HGPORT/ clone | |
|
271 | abort: HTTP request error (incomplete response; expected 385 bytes got 20) | |
|
272 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
273 | [255] | |
|
274 | 274 | |
|
275 | 275 | $ killdaemons.py $DAEMON_PIDS |
|
276 | 276 | |
@@ -461,11 +461,11 b' Server sends empty HTTP body for getbund' | |||
|
461 | 461 | $ hg --config badserver.closeaftersendbytes=933 serve -p $HGPORT -d --pid-file=hg.pid -E error.log |
|
462 | 462 | $ cat hg.pid > $DAEMON_PIDS |
|
463 | 463 | |
|
464 | TODO client spews a stack due to uncaught httplib.IncompleteRead | |
|
465 | ||
|
466 | $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null | |
|
464 | $ hg clone http://localhost:$HGPORT/ clone | |
|
467 | 465 | requesting all changes |
|
468 | [1] | |
|
466 | abort: HTTP request error (incomplete response) | |
|
467 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
468 | [255] | |
|
469 | 469 | |
|
470 | 470 | $ killdaemons.py $DAEMON_PIDS |
|
471 | 471 | |
@@ -525,11 +525,11 b' Server sends partial compression string' | |||
|
525 | 525 | $ hg --config badserver.closeaftersendbytes=945 serve -p $HGPORT -d --pid-file=hg.pid -E error.log |
|
526 | 526 | $ cat hg.pid > $DAEMON_PIDS |
|
527 | 527 | |
|
528 | TODO client spews a stack due to uncaught httplib.IncompleteRead | |
|
529 | ||
|
530 | $ hg clone http://localhost:$HGPORT/ clone 2> /dev/null | |
|
528 | $ hg clone http://localhost:$HGPORT/ clone | |
|
531 | 529 | requesting all changes |
|
532 | [1] | |
|
530 | abort: HTTP request error (incomplete response; expected 1 bytes got 3) | |
|
531 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
532 | [255] | |
|
533 | 533 | |
|
534 | 534 | $ killdaemons.py $DAEMON_PIDS |
|
535 | 535 | |
@@ -593,7 +593,8 b' Server sends partial bundle2 header magi' | |||
|
593 | 593 | |
|
594 | 594 | $ hg clone http://localhost:$HGPORT/ clone |
|
595 | 595 | requesting all changes |
|
596 | abort: connection ended unexpectedly | |
|
596 | abort: HTTP request error (incomplete response; expected 1 bytes got 3) | |
|
597 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
597 | 598 | [255] |
|
598 | 599 | |
|
599 | 600 | $ killdaemons.py $DAEMON_PIDS |
@@ -616,7 +617,8 b' Server sends incomplete bundle2 stream p' | |||
|
616 | 617 | |
|
617 | 618 | $ hg clone http://localhost:$HGPORT/ clone |
|
618 | 619 | requesting all changes |
|
619 | abort: connection ended unexpectedly | |
|
620 | abort: HTTP request error (incomplete response; expected 1 bytes got 3) | |
|
621 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
620 | 622 | [255] |
|
621 | 623 | |
|
622 | 624 | $ killdaemons.py $DAEMON_PIDS |
@@ -640,7 +642,8 b' Servers stops after bundle2 stream param' | |||
|
640 | 642 | |
|
641 | 643 | $ hg clone http://localhost:$HGPORT/ clone |
|
642 | 644 | requesting all changes |
|
643 | abort: connection ended unexpectedly | |
|
645 | abort: HTTP request error (incomplete response) | |
|
646 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
644 | 647 | [255] |
|
645 | 648 | |
|
646 | 649 | $ killdaemons.py $DAEMON_PIDS |
@@ -664,7 +667,8 b' Server stops sending after bundle2 part ' | |||
|
664 | 667 | |
|
665 | 668 | $ hg clone http://localhost:$HGPORT/ clone |
|
666 | 669 | requesting all changes |
|
667 | abort: connection ended unexpectedly | |
|
670 | abort: HTTP request error (incomplete response) | |
|
671 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
668 | 672 | [255] |
|
669 | 673 | |
|
670 | 674 | $ killdaemons.py $DAEMON_PIDS |
@@ -785,7 +789,8 b' Server stops sending after 0 length payl' | |||
|
785 | 789 | added 1 changesets with 1 changes to 1 files |
|
786 | 790 | transaction abort! |
|
787 | 791 | rollback completed |
|
788 | abort: connection ended unexpectedly | |
|
792 | abort: HTTP request error (incomplete response) | |
|
793 | (this may be an intermittent network failure; if the error persists, consider contacting the network or server operator) | |
|
789 | 794 | [255] |
|
790 | 795 | |
|
791 | 796 | $ killdaemons.py $DAEMON_PIDS |
General Comments 0
You need to be logged in to leave comments.
Login now