commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Maurice Codik Moscoso (JIRA)" <j...@apache.org>
Subject [jira] Updated: (FILEUPLOAD-136) FileUpload race condition with used with Jetty 6
Date Tue, 17 Jul 2007 18:05:05 GMT

     [ https://issues.apache.org/jira/browse/FILEUPLOAD-136?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Maurice Codik Moscoso updated FILEUPLOAD-136:
---------------------------------------------

    Attachment: TestJetty.java

I've tracked this down a little better: 

FileUpload's MultipartStream.Input class attempts to read from the underlying input stream
in it's close() method. If close() is being called because the stream threw an exception,
then this last close can have unpredictable results.

In particular, Jetty's inputstream seems to go into an infinite loop if it gets read from
after it throws EofException. The attached program reproduces this error condition. 

The output is as following:

2007-07-17 10:50:48.999::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
2007-07-17 10:50:49.000::INFO:  jetty-6.1.3
2007-07-17 10:50:49.039::INFO:  Started SocketConnector @ 0.0.0.0:10000
sending data
input stream is a org.mortbay.jetty.HttpParser$Input
caught exception: org.mortbay.jetty.EofException
trying to read again

Notice that the "last read returned .." line is never printed. At this point, my CPU is pegged
to 100% and jstack shows the following stack trace: 

Thread 30265: (state = IN_JAVA)
 - org.mortbay.jetty.HttpParser.parseNext() @bci=423, line=281 (Compiled frame; information
may be imprecise)
 - org.mortbay.jetty.HttpParser$Input.blockForContent() @bci=88, line=925 (Compiled frame)
 - org.mortbay.jetty.HttpParser$Input.read(byte[], int, int) @bci=4, line=897 (Interpreted
frame)
 - java.io.InputStream.read(byte[]) @bci=5, line=89 (Interpreted frame)
 - TestJetty$1.handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
int) @bci=132, line=42 (Interpreted frame)
 - org.mortbay.jetty.handler.HandlerWrapper.handle(java.lang.String, javax.servlet.http.HttpServletRequest,
javax.servlet.http.HttpServletResponse, int) @bci=23, line=139 (Interpreted frame)
 - org.mortbay.jetty.Server.handle(org.mortbay.jetty.HttpConnection) @bci=110, line=285 (Interpreted
frame)
 - org.mortbay.jetty.HttpConnection.handleRequest() @bci=131, line=502 (Interpreted frame)
 - org.mortbay.jetty.HttpConnection$RequestHandler.content(org.mortbay.io.Buffer) @bci=23,
line=835 (Interpreted frame)
 - org.mortbay.jetty.HttpParser.parseNext() @bci=2633, line=641 (Interpreted frame)
 - org.mortbay.jetty.HttpParser.parseAvailable() @bci=44, line=208 (Interpreted frame)
 - org.mortbay.jetty.HttpConnection.handle() @bci=122, line=378 (Interpreted frame)
 - org.mortbay.jetty.bio.SocketConnector$Connection.run() @bci=130, line=226 (Interpreted
frame)
 - org.mortbay.thread.BoundedThreadPool$PoolThread.run() @bci=45, line=442 (Interpreted frame)

At this point, I would call this both a file upload bug and a jetty bug. I'll file an issue
in Jetty's JIRA, but leaving this open so that the read() during close() thing gets fixed.


> FileUpload race condition with used with Jetty 6
> ------------------------------------------------
>
>                 Key: FILEUPLOAD-136
>                 URL: https://issues.apache.org/jira/browse/FILEUPLOAD-136
>             Project: Commons FileUpload
>          Issue Type: Bug
>    Affects Versions: 1.2
>         Environment: Running on Windows XP SP2 with Jetty 6 embedded and Firefox 2.0.0.4
>            Reporter: Keith Kowalczykowski
>            Priority: Critical
>         Attachments: FileUploadTest.zip, TestJetty.java
>
>
> When running commons file upload with Jetty 6, ServletFileUpload.parseRequest spins and
never returns when the user clicks the "stop" button in their browser while an upload is in
progress.
> Reproduction Steps:
>  * Create a simple servlet / html form which accepts a file upload using commons file
upload (or use the example code below).
>  * Upload a sufficiently large file that you have time to click the stop button before
the upload completes.
>  * Observe that the thread is now stuck within file upload.
> Other Information:
> Using jstack, I was able to get the following trace of where it is blocking. It looks
like it is on a read() call that file upload is making.
>     at org/mortbay/jetty/HttpParser$Input.blockForContent(HttpParser.java:922)
>     at org/mortbay/jetty/HttpParser$Input.read(HttpParser.java:897)
>     at org/apache/commons/fileupload/MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:959)
>     at org/apache/commons/fileupload/MultipartStream$ItemInputStream.close(MultipartStream.java:910)
>     at org/apache/commons/fileupload/util/Streams.copy(Streams.java:119)
>     at org/apache/commons/fileupload/util/Streams.copy(Streams.java:64)
>     at org/apache/commons/fileupload/FileUploadBase.parseRequest(FileUploadBase.java:354)
>     at org/apache/commons/fileupload/servlet/ServletFileUpload.parseRequest(ServletFileUpload.java:126)
>     at test/Main$1.handle(Main.java:43)
>     at org/mortbay/jetty/handler/HandlerWrapper.handle(HandlerWrapper.java:139)
>     at org/mortbay/jetty/Server.handle(Server.java:285)
>     at org/mortbay/jetty/HttpConnection.handleRequest(HttpConnection.java:502)
>     at org/mortbay/jetty/HttpConnection$RequestHandler.content(HttpConnection.java:835)
>     at org/mortbay/jetty/HttpParser.parseNext(HttpParser.java:641)
>     at org/mortbay/jetty/HttpParser.parseAvailable(HttpParser.java:208)
>     at org/mortbay/jetty/HttpConnection.handle(HttpConnection.java:378)
>     at org/mortbay/jetty/bio/SocketConnector$Connection.run(SocketConnector.java:226)
>     at org/mortbay/thread/BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)
>     at jrockit/vm/RNI.c2java(IIII)V(Native Method)
>     -- end of trac
> Originally I thought this was an issue with our code, however, I have since isolated
it to a simple test case. Bellow is a class file called Main which when run will instantiate
an instance of Jetty on port 8080 and an HTML document that will post a file upload to the
servlet. When the stop button is pressed, you will see that the line "Starting processing"
is printed, but neither the "Exception occured in processing" or "Processing completed" are
printed. I have a full eclipse project (jars and all) on my machine that I was planning on
uploading with this ticket, however, I don't see a way to attach a file. Therefore, I have
copied and pasted the two files bellow. Let me know if you want the full project.
> === Main.java ===
> /**
>  * 
>  */
> package test;
> import java.io.IOException;
> import java.util.List;
> import javax.servlet.ServletException;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
> import org.apache.commons.fileupload.FileItem;
> import org.apache.commons.fileupload.disk.DiskFileItemFactory;
> import org.apache.commons.fileupload.servlet.ServletFileUpload;
> import org.mortbay.jetty.Handler;
> import org.mortbay.jetty.Server;
> import org.mortbay.jetty.handler.AbstractHandler;
> /**
>  * @author Keith Kowalczykowski
>  * 
>  */
> public class Main {
> 	public static void main(String[] args) {
> 		Handler handler = new AbstractHandler() {
> 			public void handle(String arg0, HttpServletRequest arg1,
> 					HttpServletResponse arg2, int arg3) throws IOException,
> 					ServletException 
> 			{
> 				System.out.println("Starting processing");
> 				try
> 				{
> 					 // Create a factory for disk-based file items
> 		            DiskFileItemFactory factory = new DiskFileItemFactory();
> 		            
> 		            // Create a new file upload handler
> 		            ServletFileUpload upload = new ServletFileUpload(factory);
> 	
> 		            // Parse the request
> 		            List items = upload.parseRequest(arg1);
> 		            for (int i = 0; i < items.size(); i++)
> 		            {
> 		                FileItem file_item = (FileItem) items.get(i);
> 		                
> 		                System.out.println("Field Name: " + file_item.getFieldName());
> 		            }
> 				}
> 				catch (Exception e)
> 				{
> 					e.printStackTrace();
> 					System.out.println("Exception occured in processing");
> 				}
> 				finally
> 				{
> 					System.out.println("Processing completed");
> 				}
> 			}
> 		};
> 		try
> 		{
> 			Server server = new Server(8080);
> 			server.setHandler(handler);
> 			server.start();
> 		}
> 		catch (Exception e)
> 		{
> 			
> 		}
> 	}
> }
> === HTML Document ===
> <html>
>     <head>
>     </head>
>     <body>
>         <form name="test" action="http://localhost:8080/" method="post" enctype="multipart/form-data">
>             <input type="file" name="fileupload"/>
>             <input type="submit"/>
>         </form>
>     </body>
> </html>

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message