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

            Bug ID: 54571
           Summary: Race condition when handling comet event in thread
                    other than the serving servlet
           Product: Tomcat 6
           Version: 6.0.36
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Catalina
          Assignee: dev@tomcat.apache.org
          Reporter: david.f.w...@alcatel-lucent.com
    Classification: Unclassified

Created attachment 29958
  --> https://issues.apache.org/bugzilla/attachment.cgi?id=29958&action=edit
A werid http stream which has no http header in response

OS: Linux hostname 2.6.32-279.11.1.el6.x86_64 #1 SMP Sat Sep 22 07:10:26 EDT
2012 x86_64 x86_64 x86_64 GNU/Linux

I have a servlet which post the comet event to other thread for further
handling, there is no synchronize mechanism between this handling thread the
servlet.
And I have a simple python script as a client for testing, it act as a client:
1. make a connection to the servlet
2. send http request and check the response
3. close the connection
After  some long sequence of test above, I got a bizarre response with header
Transfer-Encoding: chunked.

The demo code is as following
[code][filename]TestServlet.java[/filename]
import javax.servlet.ServletException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import org.apache.catalina.CometEvent;
import org.apache.catalina.CometEvent.EventSubType;
import org.apache.catalina.CometProcessor;
import java.util.concurrent.LinkedBlockingQueue;

public class TestServlet extends HttpServlet implements CometProcessor {
    static String
response1="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    static String
response2="bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";

    protected ThreadModule fRunner=null;
    public void init() throws ServletException {
        fRunner=new ThreadModule();
        Thread runningThread=new Thread(fRunner,"test");
        runningThread.setDaemon(true);
        runningThread.start();
    }
    public void event(CometEvent event)   throws IOException, ServletException
{
    HttpServletRequest request = event.getHttpServletRequest();
    HttpServletResponse response = event.getHttpServletResponse();
    if (event.getEventType() == CometEvent.EventType.BEGIN) {
        //log("Begin for session: " + request.getSession(true).getId());
        if (request.getContentLength() <= 0){
            String uri = request.getRequestURI();
            if (uri.contains("HELLO")) {
                fRunner.PostMessage(new ThreadMessage(1,response));
            }
            else if (uri.contains("WORLD")){
                fRunner.PostMessage(new ThreadMessage(2,response));
            }
            else if (uri.contains("SAD")){
                fRunner.PostMessage(new ThreadMessage(3,response));
            }
            else{
                fRunner.PostMessage(new ThreadMessage(4,response));
            }
        }
    } else if (event.getEventType() == CometEvent.EventType.ERROR) {
        //log("Error for session: " + request.getSession(true).getId());
        event.close();
    } else if (event.getEventType() == CometEvent.EventType.END) {
        //log("End for session: " + request.getSession(true).getId());
        event.close();
    } else if (event.getEventType() == CometEvent.EventType.READ) {

    }
  }
  public class ThreadMessage {
      public int resType;
      public HttpServletResponse response;
      public ThreadMessage(int inresType, HttpServletResponse inresponse){
          this.resType=inresType;
          this.response=inresponse;
      }
  }
  public class ThreadModule implements Runnable {
      protected LinkedBlockingQueue<ThreadMessage> queue = new
LinkedBlockingQueue<ThreadMessage>();
      protected Object waitObject = new Object();
      public ThreadModule(){

      }
      public void PostMessage(ThreadMessage inMessage){
          queue.offer(inMessage);
          synchronized (waitObject) {
              waitObject.notify();
          }
      }
      public void HandleMessage(ThreadMessage inMessage){
          try{
          if (inMessage.resType == 1){
            inMessage.response.setStatus(200);
              PrintWriter writer = inMessage.response.getWriter();
              writer.write(response1);
              writer.close();
          }
          else if (inMessage.resType == 2){
            inMessage.response.setStatus(404);
              PrintWriter writer = inMessage.response.getWriter();
              writer.write("");
              writer.close();  
          }
          else if (inMessage.resType == 3){
                inMessage.response.setStatus(307);
                  PrintWriter writer = inMessage.response.getWriter();
                  writer.write(response2);
                  writer.close();
          }
          else{
              inMessage.response.setStatus(500);
                  PrintWriter writer = inMessage.response.getWriter();
                  writer.write("");
                  writer.close();  
          }
          }
          catch (Exception e) {

          }
      }
      public void run(){
          while (true) {
              try{
              ThreadMessage tempmessage=null;
              if (queue.isEmpty()) {
                  synchronized (waitObject) {
                        if (queue.isEmpty()){
                            waitObject.wait();
                        }
                    }
              }
              if (!queue.isEmpty()){
                  tempmessage = queue.poll();
              }
              if (tempmessage != null){
                  //sleep,if no sleep here, seems we got a race condition
                  //Thread.sleep(5);
                  HandleMessage(tempmessage);
              }
              }
              catch (Exception e) {

              }
          }
      }
  }
}
[/code]
The client testing code
[code][filename]tempclient.py[/filename/
import httplib
import time


commonheaders = {"Connection":"close"}

def GetContent(addr, requesturl, expectcode, expectbody=None, notexpect=None):
    data=None
    try:
        conn = httplib.HTTPConnection(addr)
        conn.request("GET", requesturl,'',commonheaders)
        r1 = conn.getresponse()
        rescode=r1.status
        data=r1.read()
        conn.close()
    except Exception as exp_obj:
        print "connection fail, try again"
        print exp_obj
        data=None

    if data==None:
        conn = httplib.HTTPConnection(addr)
        conn.request("GET", requesturl,'',commonheaders)
        r1 = conn.getresponse()
        rescode=r1.status
        #print rescode
        data=r1.read()
        conn.close()

    if rescode != expectcode:
        raise Exception("Fail to get
expectcode:"+str(expectcode)+",with:--"+data)
    if expectbody!=None and data.find(expectbody)== -1:
        raise Exception("Fail to find:"+expectbody+",with:--"+data)
    if notexpect!=None and data.find(notexpect)!=-1:
        raise Exception("Fail to not find:"+notexpect+",with:--"+data)


if __name__ == "__main__":
    testhost="10.90.10.119:8080"
    starttime=time.time()
    count=0
    try:
        for index in range(0,150000):
            count=count+1
            GetContent(testhost,"/david/HelloWorld/HELLO",200, "aaaaaaaa",'b')
            GetContent(testhost,"/david/HelloWorld/WORLD",404, )
            GetContent(testhost,"/david/HelloWorld/SAD",307,"bbbbbbb",'a')
    finally:
        endtime=time.time()
        totaltime=int(endtime-starttime)
        print "count:",count
        print "Time:",totaltime


[/code]

I got lots of weird http streams, one of which is attached  


I think that there is some race condition between the processing thread and the
servlet/comet thread, because if I add some delay, e.g. Thread.sleep(5);, in
the precessing thread, (which is commented in the code) no weird response
found.
And if the function for sending response is called direct in servlet
thread,(totally remove the second thread) also no werid response found.

-- 
You are receiving this mail because:
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to