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