[tahoe-dev] [tahoe-lafs] #698: corrupted file displayed to user after failure to download followed by retry
tahoe-lafs
trac at allmydata.org
Thu May 14 15:33:58 PDT 2009
#698: corrupted file displayed to user after failure to download followed by
retry
--------------------------+-------------------------------------------------
Reporter: zooko | Owner:
Type: defect | Status: new
Priority: critical | Milestone: 1.5.0
Component: code-network | Version: 1.4.1
Keywords: integrity | Launchpad_bug:
--------------------------+-------------------------------------------------
Comment(by zooko):
Okay, re topic 2 from [comment:5], I see that the corrupted page that I
get is actually the ''complete'' contents of my wiki ''with the first 2302
or 2306 bytes of it overwritten by the Twisted error messages''.
That is: my wiki begins with the following 4000 bytes:
{{{
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
<script id="versionArea" type="text/javascript">
//<![CDATA[
var version = {title: "TiddlyWiki", major: 2, minor: 5, revision: 0, date:
new Date("Mar 9, 2009"), extensions: {}};
//]]>
</script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="copyright" content="TiddlyWiki created by Jeremy Ruston,
(jeremy [at] osmosoft [dot] com)
Copyright (c) UnaMesa Association 2004-2009
Redistribution and use in source and binary forms, with or without
modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this
list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this
list of conditions and the following disclaimer in the documentation
and/or other
materials provided with the distribution.
Neither the name of the UnaMesa Association nor the names of its
contributors may be
used to endorse or promote products derived from this software without
specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS
IS' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH
DAMAGE.">
<script id="jsheadArea" type="text/javascript">
//<![CDATA[
/*
* jQuery JavaScript Library v1.3.2
* http://jquery.com/
*
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6246
*/
(function(){var
l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new
o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return
this}if(typeof E==="string"){var
G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var
I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var
F=o(I||[]);F.context=document;F.selector=E;return F}}else{return
o(H).find(E)}}else{if(o.isFunction(E)){return
o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return
this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return
this.length},get:function(E){return
E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var
G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?"
":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return
G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return
this},each:function(F,E){return o.each(this,F,E)},index:function(E){return
o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof
F==="string"){if(H===g){return
this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return
this.each(function(I){for(F in
E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return
this.attr(E,F,"curCSS")},text:function(F){if(typeof
F!=="object"&&F!=null){return
this.empty().append((this[0]&&this[0].ownerDocument||do
}}}
When I encountered this failure the first time, the first 4000 bytes of
the resulting page that I got looked like this:
{{{
<html><head><title>Exception</title></head><body><style type="text/css">
p.error {
color: black;
font-family: Verdana, Arial, helvetica, sans-serif;
font-weight: bold;
font-size: large;
margin: 0.25em;
}
div {
font-family: Verdana, Arial, helvetica, sans-serif;
}
strong.variableClass {
font-size: small;
}
div.stackTrace {
}
div.frame {
padding: 0.25em;
background: white;
border-bottom: thin black dotted;
}
div.firstFrame {
padding: 0.25em;
background: white;
border-top: thin black dotted;
border-bottom: thin black dotted;
}
div.location {
font-size: small;
}
div.snippet {
background: #FFFFDD;
padding: 0.25em;
}
div.snippetHighlightLine {
color: red;
}
span.lineno {
font-size: small;
}
pre.code {
margin: 0px;
padding: 0px;
display: inline;
font-size: small;
font-family: "Courier New", courier, monotype;
}
span.function {
font-weight: bold;
font-family: "Courier New", courier, monotype;
}
table.variables {
border-collapse: collapse;
width: 100%;
}
td.varName {
width: 1in;
vertical-align: top;
font-style: italic;
font-size: small;
padding-right: 0.25em;
}
td.varValue {
padding-left: 0.25em;
padding-right: 0.25em;
font-size: small;
}
div.variables {
margin-top: 0.5em;
}
div.dict {
background: #cccc99;
padding: 2px;
float: left;
}
td.dictKey {
background: #ffff99;
font-weight: bold;
}
td.dictValue {
background: #ffff99;
}
div.list {
background: #7777cc;
padding: 2px;
float: left;
}
div.listItem {
background: #9999ff;
}
div.instance {
width: 100%;
background: #efefef;
padding: 2px;
float: left;
}
span.instanceName {
font-size: small;
display: block;
}
span.instanceRepr {
font-family: "Courier New", courier, monotype;
}
div.function {
background: orange;
font-weight: bold;
float: left;
}
</style><a href="#tracebackEnd"><p class="error"><class
'twisted.internet.defer.FirstError'>:
FirstError(<twisted.python.failure.Failure <class
'foolscap.ipb.DeadReferenceError'>>, 2)</p></a><div
class="stackTrace"></div><a name="tracebackEnd"><p class="error"><class
'twisted.internet.defer.FirstError'>:
FirstError(<twisted.python.failure.Failure <class
'foolscap.ipb.DeadReferenceError'>>, 2)</p></a></body></html>, 19
Feb 2009)
* Revision: 6246
*/
(function(){var
l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new
o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return
this}if(typeof E==="string"){var
G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var
I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var
F=o(I||[]);F.context=document;F.selector=E;return F}}else{return
o(H).find(E)}}else{if(o.isFunction(E)){return
o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return
this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return
this.length},get:function(E){return
E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var
G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?"
":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return
G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return
this},each:function(F,E){return o.each(this,F,E)},index:function(E){return
o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof
F==="string"){if(H===g){return
this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return
this.each(function(I){for(F in
E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return
this.attr(E,F,"curCSS")},text:function(F){if(typeof
F!=="object"&&F!=null){return
this.empty().append((this[0]&&this[0].ownerDocument
}}}
See what I mean? It looks like Firefox 3.5b4 has overwritten the first
2302 or so bytes of the file with the twisted error message. Note that it
doesn't exactly line up -- the twisted error message from {{{<html>}}} to
{{{</html>}}} inclusive is 2302 bytes, but the first bytes of the original
file {{{, 19 Feb 2009)}}} I would expect to begin on byte 2306 rather than
byte 2302. Maybe there was a newline conversion or the header got subtly
rewritten a little between the time I captured the above view of "my wiki"
and the time the bad wiki was emitted.
Anyway, this makes me pretty sure that Firefox-3.5b4 is doing something
mighty funny here. Certainly I don't think Tahoe is sending those bytes
down in an HTTP response. Indeed, from the "Current Uploads Downloads"
log, we can see that Tahoe wasn't asked for the contents of the wiki at
all (the "update in MODE_READ" and the "retrieve" operations are the get
the ''directory'', not to get the actual {{{wiki.html}}} file from the
directory). Firefox-3.5b4 must have supplied the cached contents of the
wiki itself, then overwritten the first few bytes of it with the twisted
error message, then displayed it to the user. Ugh.
I suppose we should report this on the firefox issue tracker...
--
Ticket URL: <http://allmydata.org/trac/tahoe/ticket/698#comment:6>
tahoe-lafs <http://allmydata.org>
secure decentralized file storage grid
More information about the tahoe-dev
mailing list