You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@hc.apache.org by bu...@apache.org on 2003/04/29 14:56:32 UTC

DO NOT REPLY [Bug 13463] - Request/Response race condition when doing multiple requests on the same connection.

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13463>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=13463

Request/Response race condition when doing multiple requests on the same connection.

erik.van.oosten@backstream.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |



------- Additional Comments From erik.van.oosten@backstream.com  2003-04-29 12:56 -------
The following program produces the bug almost always. It uses the
util.concurrent package to let 2 threads start simultaneously.

I tried the program with the nightly build 20030429 and release 2 Alpha 1.

The program is a rewrite of mike.vannoord@brainna.com's program. But only the
main method has been changed.


import java.io.*;
import java.net.*;
import java.util.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;

import EDU.oswego.cs.dl.util.concurrent.Latch;

/**
 *
 * <br>
 * @version $Revision: $
 */
public class HttpClientRaceBug {
	/** Source control revision number */
	public static final String RCS_VERSION = "$Revision: $";
	
    public static void main(String[] args) {
        try {
            SimpleHttpServer.listen(8987);
            final HttpClient client = new HttpClient();
            client.startSession("localhost", 8987);
            client.getState().setCredentials("Test Realm",  
                new UsernamePasswordCredentials("foo", "bar"));

			final Latch go = new Latch();
			
			Thread thread1 = new Thread("1") {
				public void run() {
					try {
						go.acquire();
		                GetMethod meth = new GetMethod();
		                int lState = client.executeMethod(meth);
						byte[] aData = meth.getResponseBody();
						System.out.println("String 1: " + new String(aData));
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			};
			Thread thread2 = new Thread("2") {
				public void run() {
					try {
						go.acquire();
		                GetMethod meth = new GetMethod();
		                int lState = client.executeMethod(meth);
						byte[] aData = meth.getResponseBody();
						System.out.println("String 2: " + new String(aData));
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			};

			thread1.start();
			thread2.start();
			Thread.sleep( 1000L ); /* sleep 1s */
			
			go.release();

			Thread.sleep( 3000L ); /* sleep 3s */

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private static final class SimpleHttpServer implements Runnable {
        private Socket socket;
        public SimpleHttpServer(Socket socket) {
            this.socket = socket;
        }
        public static void listen(final int port) {
            Thread server = new Thread() {
                public void run() {
                    try {
                        ServerSocket ss = new ServerSocket(port);
                        while (true) {
                            new Thread(new 
                                SimpleHttpServer(ss.accept())).start();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            
            server.setDaemon(true);
            server.start();
        }
        public void run() {
            try {
                BufferedReader in = new BufferedReader(new 
                    InputStreamReader(this.socket.getInputStream()));
                
                int len = 0;
                boolean auth = false;
                String line;
                while ((line = in.readLine()) != null) {
                    System.out.println("> " + line);
                    
                    if (line.trim().equals("")) {
                        in.read(new char[len]);
                        doOutput(auth);
                        auth = false;
                        len = 0;
                        
                    } else if (line.indexOf(':') > -1) {
                        StringTokenizer tok = new StringTokenizer(line, ":");
                        String key = tok.nextToken().toLowerCase();
                        if (key.equals("content-length")) {
                            len = Integer.parseInt(tok.nextToken().trim());
                        } else if (key.equals("authorization")) {
                            auth = true;
                        }
                    }
                }
            } catch (Exception e) {}
        }
        private static int count = 0;
        public void doOutput(boolean authorized) throws IOException {
            Writer out = new OutputStreamWriter(this.socket.getOutputStream());
            count++;
            
            String id = (count < 100) ? 
                ((count < 10) ? "00" + count : "0" + count) : "" + count;
            if (authorized) {
                write(out, "HTTP/1.1 200 OK\r\n");
            } else {
                write(out, "HTTP/1.1 401 Unauthorized\r\n");
            }
            write(out, "WWW-Authenticate: Basic realm=\"Test Realm\"\r\n");
            write(out, "Response-Id: " + id + "\r\n");
            write(out, "Content-Type: text/html; charset=iso-8859-1\r\n");
            write(out, "Content-Length: 17\r\n\r\n");
            write(out, "My Response (" + id + ")");
            out.close();
        }
        private void write(Writer out, String text) throws IOException {
            System.out.print("< " + text);
            out.write(text);
        }
    }
}