Bug report #518 has just been filed.

You can view the report at the following URL:

   <http://znutar.cortexity.com/BugRatViewer/ShowReport/518>

REPORT #518 Details.

Project: Tomcat
Category: Bug Report
SubCategory: New Bug Report
Class: swbug
State: received
Priority: medium
Severity: serious
Confidence: public
Environment: 
   Release: 3.2
   JVM Release: 1.3
   Operating System: Win2000 Advanced
   OS Release: Win2000
   Platform: 2-CPU Pentium

Synopsis: 
JNI problem: bufferedreader.read fails in Tomcat/IIS/JNI set-up

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 

Title: BugRat Report # 518

BugRat Report # 518

Project: Tomcat Release: 3.2
Category: Bug Report SubCategory: New Bug Report
Class: swbug State: received
Priority: medium Severity: serious
Confidence: public

Submitter: Dave Smith ( [EMAIL PROTECTED] )
Date Submitted: Dec 4 2000, 04:03:30 CST
Responsible: Z_Tomcat Alias ( [EMAIL PROTECTED] )

Synopsis:
JNI problem: bufferedreader.read fails in Tomcat/IIS/JNI set-up
Environment: (jvm, os, osrel, platform)
1.3, Win2000 Advanced, Win2000, 2-CPU Pentium

Additional Environment Description:
I haven't tried this on a single-CPU box. The test machine we used is a dual-CPU Pentium III with 512 MB of RAM.

Report 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

How To Reproduce:
null

Workaround:
null

View this report online...

Reply via email to