Return-Path: Delivered-To: apmail-tomcat-dev-archive@www.apache.org Received: (qmail 72290 invoked from network); 22 Jul 2006 00:20:07 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 22 Jul 2006 00:20:07 -0000 Received: (qmail 64673 invoked by uid 500); 22 Jul 2006 00:20:00 -0000 Delivered-To: apmail-tomcat-dev-archive@tomcat.apache.org Received: (qmail 64622 invoked by uid 500); 22 Jul 2006 00:19:59 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 64611 invoked by uid 500); 22 Jul 2006 00:19:59 -0000 Delivered-To: apmail-jakarta-tomcat-dev@jakarta.apache.org Received: (qmail 64608 invoked by uid 99); 22 Jul 2006 00:19:59 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 21 Jul 2006 17:19:59 -0700 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received-SPF: pass (asf.osuosl.org: local policy) Received: from [140.211.166.113] (HELO eris.apache.org) (140.211.166.113) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 21 Jul 2006 17:19:58 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 756A11A981A; Fri, 21 Jul 2006 17:19:38 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r424503 - in /tomcat/container/tc5.5.x: catalina/src/share/org/apache/catalina/servlets/CGIServlet.java webapps/docs/changelog.xml Date: Sat, 22 Jul 2006 00:19:37 -0000 To: tomcat-dev@jakarta.apache.org From: markt@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20060722001938.756A11A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: markt Date: Fri Jul 21 17:19:37 2006 New Revision: 424503 URL: http://svn.apache.org/viewvc?rev=424503&view=rev Log: Partial fix for bug part of 34801. Add handling of IOExceptions during long running CGI requests. Modified: tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java tomcat/container/tc5.5.x/webapps/docs/changelog.xml Modified: tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java?rev=424503&r1=424502&r2=424503&view=diff ============================================================================== --- tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java (original) +++ tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/servlets/CGIServlet.java Fri Jul 21 17:19:37 2006 @@ -1685,103 +1685,118 @@ command.append(cmdAndArgs.toString()); cmdAndArgs = command; - rt = Runtime.getRuntime(); - proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd); - - String sContentLength = (String) env.get("CONTENT_LENGTH"); - - if(!"".equals(sContentLength)) { - commandsStdIn = new BufferedOutputStream(proc.getOutputStream()); - IOTools.flow(stdin, commandsStdIn); - commandsStdIn.flush(); - commandsStdIn.close(); - } - - /* we want to wait for the process to exit, Process.waitFor() - * is useless in our situation; see - * http://developer.java.sun.com/developer/ - * bugParade/bugs/4223650.html - */ - - boolean isRunning = true; - commandsStdErr = new BufferedReader - (new InputStreamReader(proc.getErrorStream())); - final BufferedReader stdErrRdr = commandsStdErr ; + try { + rt = Runtime.getRuntime(); + proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd); + + String sContentLength = (String) env.get("CONTENT_LENGTH"); - new Thread() { - public void run () { - sendToLog(stdErrRdr) ; - } ; - }.start() ; + if(!"".equals(sContentLength)) { + commandsStdIn = new BufferedOutputStream(proc.getOutputStream()); + IOTools.flow(stdin, commandsStdIn); + commandsStdIn.flush(); + commandsStdIn.close(); + } - InputStream cgiHeaderStream = - new HTTPHeaderInputStream(proc.getInputStream()); - BufferedReader cgiHeaderReader = - new BufferedReader(new InputStreamReader(cgiHeaderStream)); + /* we want to wait for the process to exit, Process.waitFor() + * is useless in our situation; see + * http://developer.java.sun.com/developer/ + * bugParade/bugs/4223650.html + */ + + boolean isRunning = true; + commandsStdErr = new BufferedReader + (new InputStreamReader(proc.getErrorStream())); + final BufferedReader stdErrRdr = commandsStdErr ; + + new Thread() { + public void run () { + sendToLog(stdErrRdr) ; + } ; + }.start() ; + + InputStream cgiHeaderStream = + new HTTPHeaderInputStream(proc.getInputStream()); + BufferedReader cgiHeaderReader = + new BufferedReader(new InputStreamReader(cgiHeaderStream)); - while (isRunning) { - try { - //set headers - String line = null; - while (((line = cgiHeaderReader.readLine()) != null) - && !("".equals(line))) { - if (debug >= 2) { - log("runCGI: addHeader(\"" + line + "\")"); - } - if (line.startsWith("HTTP")) { - response.setStatus(getSCFromHttpStatusLine(line)); - } else if (line.indexOf(":") >= 0) { - String header = - line.substring(0, line.indexOf(":")).trim(); - String value = - line.substring(line.indexOf(":") + 1).trim(); - if (header.equalsIgnoreCase("status")) { - response.setStatus(getSCFromCGIStatusHeader(value)); + while (isRunning) { + try { + //set headers + String line = null; + while (((line = cgiHeaderReader.readLine()) != null) + && !("".equals(line))) { + if (debug >= 2) { + log("runCGI: addHeader(\"" + line + "\")"); + } + if (line.startsWith("HTTP")) { + response.setStatus(getSCFromHttpStatusLine(line)); + } else if (line.indexOf(":") >= 0) { + String header = + line.substring(0, line.indexOf(":")).trim(); + String value = + line.substring(line.indexOf(":") + 1).trim(); + if (header.equalsIgnoreCase("status")) { + response.setStatus(getSCFromCGIStatusHeader(value)); + } else { + response.addHeader(header , value); + } } else { - response.addHeader(header , value); + log("runCGI: bad header line \"" + line + "\""); } - } else { - log("runCGI: bad header line \"" + line + "\""); } - } - - //write output - byte[] bBuf = new byte[2048]; - - OutputStream out = response.getOutputStream(); - cgiOutput = proc.getInputStream(); - - try { - while ((bufRead = cgiOutput.read(bBuf)) != -1) { - if (debug >= 4) { - log("runCGI: output " + bufRead + - " bytes of data"); + + //write output + byte[] bBuf = new byte[2048]; + + OutputStream out = response.getOutputStream(); + cgiOutput = proc.getInputStream(); + + try { + while ((bufRead = cgiOutput.read(bBuf)) != -1) { + if (debug >= 4) { + log("runCGI: output " + bufRead + + " bytes of data"); + } + out.write(bBuf, 0, bufRead); + } + } finally { + // Attempt to consume any leftover byte if something bad happens, + // such as a socket disconnect on the servlet side; otherwise, the + // external process could hang + if (bufRead != -1) { + while ((bufRead = cgiOutput.read(bBuf)) != -1) {} } - out.write(bBuf, 0, bufRead); } - } finally { - // Attempt to consume any leftover byte if something bad happens, - // such as a socket disconnect on the servlet side; otherwise, the - // external process could hang - if (bufRead != -1) { - while ((bufRead = cgiOutput.read(bBuf)) != -1) {} + + proc.exitValue(); // Throws exception if alive + + isRunning = false; + + } catch (IllegalThreadStateException e) { + try { + Thread.sleep(500); + } catch (InterruptedException ignored) { } } + } //replacement for Process.waitFor() - proc.exitValue(); // Throws exception if alive - - isRunning = false; - - } catch (IllegalThreadStateException e) { - try { - Thread.sleep(500); - } catch (InterruptedException ignored) { - } + // Close the output stream used + cgiOutput.close(); + } + catch (IOException e){ + log ("Caught exception " + e); + throw new IOException (e.toString()); + } + finally{ + if (debug > 4) { + log ("Running finally block"); } - } //replacement for Process.waitFor() - - // Close the output stream used - cgiOutput.close(); + if (proc != null){ + proc.destroy(); + proc = null; + } + } } /** Modified: tomcat/container/tc5.5.x/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/container/tc5.5.x/webapps/docs/changelog.xml?rev=424503&r1=424502&r2=424503&view=diff ============================================================================== --- tomcat/container/tc5.5.x/webapps/docs/changelog.xml (original) +++ tomcat/container/tc5.5.x/webapps/docs/changelog.xml Fri Jul 21 17:19:37 2006 @@ -56,6 +56,10 @@ query string via the QUERY_STRING environment variable; provide POST content unmodified to stdin; and never call getParameters(). (markt) + + 34801: Partial fix that adds handling of IOExceptions during + long running CGI requests. Based on a patch by Chris Davey. (markt) + --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org For additional commands, e-mail: dev-help@tomcat.apache.org