https://issues.apache.org/bugzilla/show_bug.cgi?id=45601

           Summary: Static Content Corruption
           Product: Tomcat 5
           Version: 5.5.20
          Platform: Sun
        OS/Version: Solaris
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Catalina
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


This problem is seen to happen in Tomcat 5.5.20 and 6.0.16
as well as SJAS81/82PE.  In some cases when the issue occurs one will see:

SEVERE: Servlet.service() for servlet default threw exception
java.io.IOException: Bad file number
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:194)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:254)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:313)
        at java.io.FilterInputStream.read(FilterInputStream.java:90)
        at
org.apache.catalina.servlets.DefaultServlet.copyRange(DefaultServlet.java:1993)
        at
org.apache.catalina.servlets.DefaultServlet.copy(DefaultServlet.java:1739)
        at
org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:824)

It has currently only been reproduced on a Sparc T1 machine.

Root cause:

An optimization in org.apache.catalina.servlets.DefaultServlet copy
(CacheEntry, InputStream, ServletOutputStream) was introduced in tomcat 5.5. 
This optimization is getting the binary content into a byte buffer from the
cache and writes directly to ServletOutputStream using ServletOutputStream's
write method.  The ServletOutputStream implementation also uses its its own
buffering for writing the byte buffer, while writing bytes using write(b, off,
len) is not guaranteed to be in order.  In a highly threaded environment
ServletOutputStream's write method gets accessed by multiple threads, so
ServletOutputStream's write method may sometimes get called while the previous
thread's writing of the byte buffer is not yet finished or its own buffer is
not yet flushed, which results in corrupted output.

Fix:

The fix is to remove this optimization.  Said removal is expected to result in
a negligible performance impact.  We would still be using cache entries and the
copying of cache contents to ServletOutputStream would be done using
BufferedInputStream which remains efficient.

Here is the diff for the fix as applied to Sun's Appserver:

Index: DefaultServlet.java
===================================================================
RCS file:
/m/jws/appserv-webtier/src_imported/jakarta-tomcat-catalina/catalina/s
rc/share/org/apache/catalina/servlets/DefaultServlet.java,v
retrieving revision 1.6
diff -u -r1.6 DefaultServlet.java
--- DefaultServlet.java 1 Nov 2004 19:40:13 -0000       1.6
+++ DefaultServlet.java 18 Jul 2008 12:02:47 -0000
@@ -1758,14 +1758,7 @@
         IOException exception = null;
         InputStream resourceInputStream = null;

-        // Optimization: If the binary content has already been loaded, send
-        // it directly
         if (cacheEntry.resource != null) {
-            byte buffer[] = cacheEntry.resource.getContent();
-            if (buffer != null) {
-                ostream.write(buffer, 0, buffer.length);
-                return;
-            }
             resourceInputStream = cacheEntry.resource.streamContent();
         } else {
             resourceInputStream = is;


-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to