You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Krešimir Pavić <Kr...@iskon.hr> on 2004/10/13 18:36:57 UTC

CGIRunner (at CGIServlet) problem

Hi!

  I've found a problem in CGI module (servlets-cgi.jar) in Tomcat distribution.
  The problem occures in some occasions that are hard to reproduce. 
  We have Tomcat that invokes some CGI (webmail) on Linux (Debian).
  Everthings worked fine, but
  after few days we discoverd lots of cgi programms that are hanged in WRITE mode.
  So after a week, we needed fast restart of Tomcat (OutOfMemoryError -> hanging 
  forked proceses).

  Problem was detected in next few line (thread that reads from forked process and
  wirites data to client). In few occasions we catched this exception:
   java.net.SocketExcpetion: ClientAbortException (in code below)
  and our forked process didn't finish
  his work and remained hanging (in write mode ), but sometimes we got this exception:
   java.net.SocketException: Broken pipe (in catalina.out) and forked process finished 
  his work as supposed.
  Both exceptions are thrown wheb client closes his/her browser before anthing appears.
  First excpetion is very hard to reproduce (try it :-).

  The solution is to add try-catch block in while loop. With this modification, any
  forked process will finish his work and be able to write the complete content 
  (somewhere).

  while ((bufRead = commandsStdOut.read(cBuf)) != -1) {
   if (servletContainerStdout != null) {
      if (debug >= 4) {
         log("runCGI: write(\"" + new String(cBuf, 0, bufRead) + "\")");
      }

      /////////////////////////////
      // new code

      try {
        servletContainerStdout.write(cBuf, 0, bufRead); // old line
      } catch (java.net.SocketException se {
      servletContainerStdout = null;

      // end of new code
      ////////////////////////

   }
  }

              kresimir

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


Re: CGIRunner (at CGIServlet) problem

Posted by Remy Maucherat <re...@apache.org>.
Krešimir Pavić wrote:

>Hi!
>
>  I've found a problem in CGI module (servlets-cgi.jar) in Tomcat distribution.
>  The problem occures in some occasions that are hard to reproduce. 
>  We have Tomcat that invokes some CGI (webmail) on Linux (Debian).
>  Everthings worked fine, but
>  after few days we discoverd lots of cgi programms that are hanged in WRITE mode.
>  So after a week, we needed fast restart of Tomcat (OutOfMemoryError -> hanging 
>  forked proceses).
>
>  Problem was detected in next few line (thread that reads from forked process and
>  wirites data to client). In few occasions we catched this exception:
>   java.net.SocketExcpetion: ClientAbortException (in code below)
>  and our forked process didn't finish
>  his work and remained hanging (in write mode ), but sometimes we got this exception:
>   java.net.SocketException: Broken pipe (in catalina.out) and forked process finished 
>  his work as supposed.
>  Both exceptions are thrown wheb client closes his/her browser before anthing appears.
>  First excpetion is very hard to reproduce (try it :-).
>
>  The solution is to add try-catch block in while loop. With this modification, any
>  forked process will finish his work and be able to write the complete content 
>  (somewhere).
>
>  while ((bufRead = commandsStdOut.read(cBuf)) != -1) {
>   if (servletContainerStdout != null) {
>      if (debug >= 4) {
>         log("runCGI: write(\"" + new String(cBuf, 0, bufRead) + "\")");
>      }
>
>      /////////////////////////////
>      // new code
>
>      try {
>        servletContainerStdout.write(cBuf, 0, bufRead); // old line
>      } catch (java.net.SocketException se {
>      servletContainerStdout = null;
>
>      // end of new code
>      ////////////////////////
>
>   }
>  }
>
With your code, there could also be numerous exceptions being caught, 
again not something optimal.

I think the best would be to do the rest of the reading in a finally block.
try{
                        while ((bufRead = commandsStdOut.read(cBuf)) != 
-1) {
                            if (servletContainerStdout != null) {
                                if (debug >= 4) {
                                    log("runCGI: write(\"" +
                                        new String(cBuf, 0, bufRead) + 
"\")");
                                }
                                servletContainerStdout.write(cBuf, 0, 
bufRead);
                            }
                        }
} finally {
    if (bufRead != -1) {
       while ((bufRead = commandsStdOut.read(cBuf)) != -1) {}
    }
}

I got to see some of the surrounding code, and I also don't understand:
            BufferedWriter servletContainerStdout = null;
            try {
                if (response.getOutputStream() != null) {
                    servletContainerStdout =
                        new BufferedWriter(new OutputStreamWriter
                            (response.getOutputStream()));
                }
            } catch (IOException ignored) {
                //NOOP: no output will be written
            }
How about removing that stuff and replacing it with 
servletContainerStdout = response.getWriter() ? What would the 
difference be ?

Anyone caring about CGI who would want to optimize the CGI servlet ? 
(Mladen ? ;) )
(a good start would be to publish benchmarks of Tomcat + CGI vs Apache 
to show how good or how bad it is, and where we stand)

Rémy


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