You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2001/03/10 04:13:53 UTC

[Bug 276] New - JNI problem: bufferedreader.read fails in Tomcat/IIS/JNI set-up BugRat Report#518

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

*** shadow/276	Fri Mar  9 19:13:52 2001
--- shadow/276.tmp.11958	Fri Mar  9 19:13:52 2001
***************
*** 0 ****
--- 1,256 ----
+ +============================================================================+
+ | JNI problem: bufferedreader.read fails in Tomcat/IIS/JNI set-up BugRat Rep |
+ +----------------------------------------------------------------------------+
+ |        Bug #: 276                         Product: Tomcat 3                |
+ |       Status: UNCONFIRMED                 Version: 3.2.1 Final             |
+ |   Resolution:                            Platform: All                     |
+ |     Severity: Normal                   OS/Version: All                     |
+ |     Priority: High                      Component: Connectors              |
+ +----------------------------------------------------------------------------+
+ |  Assigned To: danmil@shore.net                                             |
+ |  Reported By: dave_smith@mapinfo.com                                       |
+ |      CC list: Cc:                                                          |
+ +----------------------------------------------------------------------------+
+ |          URL:                                                              |
+ +============================================================================+
+ |                              DESCRIPTION                                   |
+ There seems to be a bug that interferes with servlet-to-servlet communication, when Tomcat is running under IIS (Win 2000 Advanced), using JNI.  
+ 
+ I'm attaching source for a pair of simple servlets that demonstrate the bug.  The first servlet (BadClient.java) opens a URLConnection to the second servlet (BadServer.java).   BadClient uses the URLConnection to open an output stream, then uses the output stream to print some text, which will be read by BadServer.  
+ 
+ The BadServer servlet then calls request.getReader to get a reader object, to read the text that was sent by BadClient. 
+ 
+ This all works fine under Tomcat 3.2, when Tomcat is running stand-alone. But if Tomcat 3.2 is running inside IIS, using the JNI connector, there's a problem.   BadServer is never able to read any of the text sent by BadClient.   The whole process just seems to hang for exactly 1 minute... apparently, something times out after 1 minute, and BadClient stops trying to read the text.  Under JNI, the read call returns -1.  
+ 
+ (Other servlets work fine under JNI.) 
+ 
+ The two servlets go on and perform other tasks after that, with BadServer reading a local .GIF file, then sending it back to BadClient, which send the image back to the browser.  That part works; it's the first part that fails, as described above. 
+ 
+ I've tried various configurations of Tomcat -- using the JVM.DLL for classic, or hotspot, or server (Java 1.3).   No difference.  I've looked in the various log files for exceptions, and I don't see any.
+ 
+ Here's the source for both servlets (around 100 lines each). If the formatting is messed up too badly, please let me know and I'll email a copy to anyone who wants to investigate the problem. 
+ 
+ // Here is all of BadClient.java (118 lines): 
+ // BadClient.java -- demonstrates behavior that works fine in Tomcat 3.2
+ // but does not work when Tomcat runs under IIS using JNI
+ // Used in conjunction with BadServer.java
+ import javax.servlet.*;
+ import javax.servlet.http.*;
+ import java.io.*;
+ import java.util.*;
+ import java.net.URLConnection;
+ import java.net.URL;
+ 
+ public class BadClient extends HttpServlet {
+ 
+ 	// TODO:  Either modify the following string literal to represent
+ 	// the URL of the BadServer servlet, or specify that URL
+ 	// using an init parameter.
+ 	String m_url = "http://localhost:8100/test/servlet/BadServer";
+ 
+ 	public void init(ServletConfig config) throws ServletException {
+ 		super.init(config);
+ 		try {
+ 			String str = getInitParameter("url"); 		//URL to 2nd servlet
+ 			if (str != null) {
+ 				m_url = str;
+ 			}
+ 		}
+ 		catch (Exception e) {
+ 			e.printStackTrace();
+ 		}
+ 	}
+ 
+ 	public void service(HttpServletRequest request, HttpServletResponse res)
+ 		throws ServletException, IOException
+ 	{
+ 		// Open an URLConnection to the BadServer servlet.
+ 		URL url = new URL(m_url);
+ 		URLConnection urlConnection = url.openConnection();
+ 		urlConnection.setDoOutput(true);
+ 		urlConnection.setUseCaches(false);
+ 		urlConnection.setRequestProperty("Connection", "close");
+ 		OutputStream os = null;
+ 		try {
+ 			os = urlConnection.getOutputStream();
+ 
+ 			// Only use one of the following two statements:
+ 			//PrintWriter pw = new PrintWriter(os);
+ 			OutputStreamWriter pw = new OutputStreamWriter(os);
+ 
+ 			System.out.println("BadClient: About to print text. Time:" + new Date());
+ 
+ 			// Send some text to the second servlet.  This is the part that
+ 			// seems to fail when running on Tomcat 3.2 under IIS using JNI.
+ 
+ 			// If using a PrintWriter, use the println method...
+ 			/*
+ 			if (pw.checkError()) {
+ 				System.out.println("BadClient: will do println; checkError is true.");
+ 			}
+ 			pw.println("This is some text sent from BadClient to BadServer.");
+ 			if (pw.checkError()) {
+ 				System.out.println("BadClient: just did println; checkError is true.");
+ 			}
+ 			*/
+ 
+ 			// ...OR, If using an OutputStreamWriter, use this statement:
+ 			pw.write("This is some text sent from BadClient to BadServer...", 0, 50);
+ 
+ 			System.out.println("BadClient: Sent text.  Time:" + new Date());
+ 
+ 			String foo = request.getParameter("skipflush");
+ 			if (foo != null && foo.length() > 0) {
+ 				System.out.println("BadClient: Will SKIP the pw.flush...");
+ 			}
+ 			else {
+ 				pw.flush();
+ 			}
+ 
+ 			foo = request.getParameter("skipclose");
+ 			if (foo != null && foo.length() > 0 ) {
+ 				System.out.println("Will SKIP the pw.close... ");
+ 			}
+ 			else {
+ 				pw.close();
+ 			}
+ 
+ 			System.out.println("BadClient:After flush & close. Time:" + new Date());
+ 		} catch (Exception e) {
+ 			System.out.println(e.toString() );
+ 			e.printStackTrace();
+ 		}
+ 		os.close();
+ 
+ 		// Fetch an image from the second servlet
+ 		BufferedInputStream bin =
+ 				new BufferedInputStream( urlConnection.getInputStream() );
+ 
+ 		DataInputStream dis = new DataInputStream(bin);
+ 
+ 		// Read the text that precedes the image that we'll get back
+ 		String s = dis.readUTF();
+ 		System.out.println("BadClient: Read header from BadServer: {" + s + "}");
+ 
+ 		byte[] buf = new byte[1024];
+ 		int    count;
+ 		// now pump the image data to the browser
+ 		OutputStream outStream = res.getOutputStream();
+ 		while ((count = dis.read(buf)) != -1) {
+ 			outStream.write(buf, 0, count);
+ 		}
+ 		outStream.flush();
+ 		dis.close();
+ 		outStream.close();
+ 	}
+ 
+ 	public String getServletInfo() {
+ 		return "ClientServlet Info";
+ 	}
+ }
+ // end of BadClient.java 
+ 
+ //Here is all of BadServer.java (101 lines): 
+ 
+ // BadServer.java -- demonstrates behavior that works fine in Tomcat 3.2
+ // but does not work if Tomcat is running under IIS with JNI.
+ // Used in conjunction with BadClient.java
+ 
+ import javax.servlet.*;
+ import javax.servlet.http.*;
+ import java.io.*;
+ import java.util.*;
+ public class BadServer extends HttpServlet {
+ 
+ 	public void init(ServletConfig config) throws ServletException {
+ 		super.init(config);
+ 	}
+ 
+ 	public void doPost(HttpServletRequest request, HttpServletResponse res)
+ 		throws ServletException, IOException {
+ 
+ 		try {
+ 			System.out.println("BadServer: will read text fromclient.:" + new Date());
+ 
+ 			// Read in the text sent by the client servlet.
+ 
+ 			// Only make one of the following two calls:
+ 			useBufferedReader(request);
+ 			//useInputStreamReader(request);
+ 
+ 			System.out.println("BadServer: read text from the client.:" + new Date());
+ 		}
+ 		catch (Exception e) {
+ 			System.out.println(e.toString() );
+ 			e.printStackTrace();
+ 		}
+ 
+ 		// Send the client back some text, followed by a GIF image
+ 		returnFile(res);
+ 	}
+ 
+ 	void useInputStreamReader(HttpServletRequest request)
+ 				throws IOException {
+ 
+ 		String buf = null;
+ 		int i = 0;
+ 		try {
+ 			InputStream is = request.getInputStream();
+ 			InputStreamReader br = new InputStreamReader(is);
+ 
+ 			char[] cbuf = new char[1024];
+ 			i = br.read(cbuf, 0, 50);
+ 			buf = new String(cbuf);
+ 		} catch (Exception e) {
+ 			System.out.println(e.toString() );
+ 			e.printStackTrace();
+ 		}
+ 		System.out.println("BadServer:read returned " + i + " chars:" + buf);
+ 	}
+ 
+ 	void useBufferedReader(HttpServletRequest request)
+ 				throws IOException {
+ 		//InputStream is = request.getInputStream();
+ 		//BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ 
+ 		String buf = null;
+ 		int i = 0;
+ 		try {
+ 			BufferedReader br = request.getReader();
+ 			char[] cbuf = new char[1024];
+ 			i = br.read(cbuf, 0, 50);  
+ 			buf = new String(cbuf);
+ 		} catch (Exception e) {
+ 			System.out.println(e.toString() );
+ 			e.printStackTrace();
+ 		}
+ 		System.out.println("BadServer:readLine returned " + i + " chars:" + buf);
+ 	}
+ 
+ 	void returnFile(HttpServletResponse res)
+ 			throws ServletException, IOException {
+ 
+ 		// TODO:  If necessary, modify the following to point to a local GIF file.
+ 		File f = new File("D:\\test.gif");
+ 
+ 		BufferedInputStream bin = new BufferedInputStream(new FileInputStream(f));
+ 		BufferedOutputStream os = new BufferedOutputStream(res.getOutputStream());
+ 		DataOutputStream dos = new DataOutputStream(os);
+ 		dos.writeUTF("Some text sent from BadServer!");
+ 
+ 		byte[] buf = new byte[1024];
+ 		int nRead;
+ 
+ 		while( (nRead = bin.read(buf)) != -1 ) {
+ 				os.write(buf, 0, nRead);
+ 		}
+ 		os.flush();
+ 		bin.close();
+ 		System.out.println("BadServer: Flushed OS.");
+ 	}
+ 
+ 	public String getServletInfo() {
+ 		return "SecondServlet Information";
+ 	}
+ }
+ // end of BadServer.java 

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