Uploaded image for project: 'SonarQube'
  1. SonarQube
  2. SONAR-8321

Improve error handling when error is thrown by web service

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 6.2
    • Component/s: Web API
    • Labels:

      Description

      Sometimes, when a web service request is aborted for an unknown reason, the expected exception ClientAbortException is not thrown but the request is commited => this generated some useless stacktrace, here's an example

      2016.10.19 15:50:17 ERROR web[][o.s.s.p.w.RootFilter] Processing of request /js/bundles/vendor.js?v=6.1 failed
      org.apache.catalina.connector.ClientAbortException: java.io.IOException: Connection reset by peer
      	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:339) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:418) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:406) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:97) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.servlets.DefaultServlet.copyRange(DefaultServlet.java:2128) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.servlets.DefaultServlet.copy(DefaultServlet.java:1971) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:968) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:398) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.jruby.rack.RackFilter.doFilterInternal(RackFilter.java:78) ~[jruby-rack-1.1.13.2.jar:na]
      	at org.jruby.rack.UnmappedRackFilter.isDoDispatch(UnmappedRackFilter.java:106) ~[jruby-rack-1.1.13.2.jar:na]
      	at org.jruby.rack.AbstractFilter.isDoDispatch(AbstractFilter.java:107) ~[jruby-rack-1.1.13.2.jar:na]
      	at org.jruby.rack.AbstractFilter.doFilter(AbstractFilter.java:65) ~[jruby-rack-1.1.13.2.jar:na]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.sonar.server.platform.web.SecurityServletFilter.doHttpFilter(SecurityServletFilter.java:59) ~[sonar-server-6.1.jar:na]
      	at org.sonar.server.platform.web.SecurityServletFilter.doFilter(SecurityServletFilter.java:49) ~[sonar-server-6.1.jar:na]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.sonar.server.platform.web.MasterServletFilter$GodFilterChain.doFilter(MasterServletFilter.java:128) ~[sonar-server-6.1.jar:na]
      	at org.sonar.server.platform.web.MasterServletFilter.doFilter(MasterServletFilter.java:95) ~[sonar-server-6.1.jar:na]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.sonar.server.user.UserSessionFilter.doFilter(UserSessionFilter.java:60) ~[sonar-server-6.1.jar:na]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.sonar.server.platform.web.RoutesFilter.doFilter(RoutesFilter.java:55) ~[sonar-server-6.1.jar:na]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.sonar.server.platform.web.RootFilter.doFilter(RootFilter.java:113) ~[sonar-server-6.1.jar:na]
      	at org.sonar.server.platform.web.RootFilter.doFilter(RootFilter.java:81) ~[sonar-server-6.1.jar:na]
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:191) [logback-access-1.1.3.jar:na]
      	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_101]
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_101]
      	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.32.jar:8.0.32]
      	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
      Caused by: java.io.IOException: Connection reset by peer
      	at sun.nio.ch.FileDispatcherImpl.write0(Native Method) ~[na:1.8.0_101]
      	at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47) ~[na:1.8.0_101]
      	at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[na:1.8.0_101]
      	at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[na:1.8.0_101]
      	at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[na:1.8.0_101]
      	at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:124) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:172) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.InternalNioOutputBuffer.writeToSocket(InternalNioOutputBuffer.java:139) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.InternalNioOutputBuffer.addToBB(InternalNioOutputBuffer.java:197) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.InternalNioOutputBuffer.access$000(InternalNioOutputBuffer.java:41) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.InternalNioOutputBuffer$SocketOutputBuffer.doWrite(InternalNioOutputBuffer.java:320) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:116) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.filters.GzipOutputFilter$FakeOutputStream.write(GzipOutputFilter.java:177) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:253) ~[na:1.8.0_101]
      	at java.util.zip.DeflaterOutputStream.write(DeflaterOutputStream.java:211) ~[na:1.8.0_101]
      	at java.util.zip.GZIPOutputStream.write(GZIPOutputStream.java:145) ~[na:1.8.0_101]
      	at org.apache.coyote.http11.filters.GzipOutputFilter.doWrite(GzipOutputFilter.java:79) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.java:256) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.coyote.Response.doWrite(Response.java:501) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:388) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
      	... 52 common frames omitted
      

      Technical details :
      In WebServiceEngine#execute, we should move the code done when a ClientAbortException is generated at the begin of #sendErrors by doing something like :

        private void sendErrors(Response response, int status, Errors errors) {
          Response.Stream stream = response.stream();
          if (stream instanceof ServletResponse.ServletStream) {
            ServletResponse.ServletStream servletStream = ((ServletResponse.ServletStream) stream);
            if (servletStream.response().isCommitted()) {
              // Request has been aborted by the client, nothing can been done as Tomcat has committed the response
              LOGGER.debug("Request {} has been aborted by client, error is '{}'", request, e.getMessage());
              return;
            }
            servletStream.reset();
          }
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                julien.lancelot Julien Lancelot
                Reporter:
                julien.lancelot Julien Lancelot
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Due:
                  Created:
                  Updated:
                  Resolved: