Search in sources :

Example 1 with CloseNowException

use of org.apache.coyote.CloseNowException in project tomcat by apache.

the class Stream method reserveWindowSize.

final synchronized int reserveWindowSize(int reservation, boolean block) throws IOException {
    long windowSize = getWindowSize();
    while (windowSize < 1) {
        if (!canWrite()) {
            throw new CloseNowException(sm.getString("stream.notWritable", getConnectionId(), getIdAsString()));
        }
        if (block) {
            try {
                long writeTimeout = handler.getProtocol().getStreamWriteTimeout();
                allocationManager.waitForStream(writeTimeout);
                windowSize = getWindowSize();
                if (windowSize == 0) {
                    doStreamCancel(sm.getString("stream.writeTimeout"), Http2Error.ENHANCE_YOUR_CALM);
                }
            } catch (InterruptedException e) {
                // Stream.
                throw new IOException(e);
            }
        } else {
            allocationManager.waitForStreamNonBlocking();
            return 0;
        }
    }
    int allocation;
    if (windowSize < reservation) {
        allocation = (int) windowSize;
    } else {
        allocation = reservation;
    }
    decrementWindowSize(allocation);
    return allocation;
}
Also used : CloseNowException(org.apache.coyote.CloseNowException) IOException(java.io.IOException)

Example 2 with CloseNowException

use of org.apache.coyote.CloseNowException in project tomcat by apache.

the class Http2UpgradeHandler method reserveWindowSize.

int reserveWindowSize(Stream stream, int reservation) throws IOException {
    // Need to be holding the stream lock so releaseBacklog() can't notify
    // this thread until after this thread enters wait()
    int allocation = 0;
    synchronized (stream) {
        do {
            synchronized (this) {
                if (!stream.canWrite()) {
                    throw new CloseNowException(sm.getString("upgradeHandler.stream.notWritable", stream.getConnectionId(), stream.getIdentifier()));
                }
                long windowSize = getWindowSize();
                if (windowSize < 1 || backLogSize > 0) {
                    // Has this stream been granted an allocation
                    int[] value = backLogStreams.get(stream);
                    if (value == null) {
                        value = new int[] { reservation, 0 };
                        backLogStreams.put(stream, value);
                        backLogSize += reservation;
                        // Add the parents as well
                        AbstractStream parent = stream.getParentStream();
                        while (parent != null && backLogStreams.putIfAbsent(parent, new int[2]) == null) {
                            parent = parent.getParentStream();
                        }
                    } else {
                        if (value[1] > 0) {
                            allocation = value[1];
                            decrementWindowSize(allocation);
                            if (value[0] == 0) {
                                // The reservation has been fully allocated
                                // so this stream can be removed from the
                                // backlog.
                                backLogStreams.remove(stream);
                            } else {
                                // This allocation has been used. Reset the
                                // allocation to zero. Leave the stream on
                                // the backlog as it still has more bytes to
                                // write.
                                value[1] = 0;
                            }
                        }
                    }
                } else if (windowSize < reservation) {
                    allocation = (int) windowSize;
                    decrementWindowSize(allocation);
                } else {
                    allocation = reservation;
                    decrementWindowSize(allocation);
                }
            }
            if (allocation == 0) {
                try {
                    stream.wait();
                } catch (InterruptedException e) {
                    throw new IOException(sm.getString("upgradeHandler.windowSizeReservationInterrupted", connectionId, stream.getIdentifier(), Integer.toString(reservation)), e);
                }
            }
        } while (allocation == 0);
    }
    return allocation;
}
Also used : CloseNowException(org.apache.coyote.CloseNowException) IOException(java.io.IOException)

Example 3 with CloseNowException

use of org.apache.coyote.CloseNowException in project tomcat by apache.

the class StandardWrapperValve method invoke.

// --------------------------------------------------------- Public Methods
/**
 * Invoke the servlet we are managing, respecting the rules regarding
 * servlet lifecycle support.
 *
 * @param request Request to be processed
 * @param response Response to be produced
 *
 * @exception IOException if an input/output error occurred
 * @exception ServletException if a servlet error occurred
 */
@Override
public final void invoke(Request request, Response response) throws IOException, ServletException {
    // Initialize local variables we may need
    boolean unavailable = false;
    Throwable throwable = null;
    // This should be a Request attribute...
    long t1 = System.currentTimeMillis();
    requestCount.incrementAndGet();
    StandardWrapper wrapper = (StandardWrapper) getContainer();
    Servlet servlet = null;
    Context context = (Context) wrapper.getParent();
    // Check for the application being marked unavailable
    if (!context.getState().isAvailable()) {
        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable"));
        unavailable = true;
    }
    // Check for the servlet being marked unavailable
    if (!unavailable && wrapper.isUnavailable()) {
        container.getLogger().info(sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        long available = wrapper.getAvailable();
        if ((available > 0L) && (available < Long.MAX_VALUE)) {
            response.setDateHeader("Retry-After", available);
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        } else if (available == Long.MAX_VALUE) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
        }
        unavailable = true;
    }
    // Allocate a servlet instance to process this request
    try {
        if (!unavailable) {
            servlet = wrapper.allocate();
        }
    } catch (UnavailableException e) {
        container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
        long available = wrapper.getAvailable();
        if ((available > 0L) && (available < Long.MAX_VALUE)) {
            response.setDateHeader("Retry-After", available);
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        } else if (available == Long.MAX_VALUE) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
        }
    } catch (ServletException e) {
        container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
        throwable = e;
        exception(request, response, e);
    } catch (Throwable e) {
        ExceptionUtils.handleThrowable(e);
        container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
        throwable = e;
        exception(request, response, e);
        servlet = null;
    }
    MessageBytes requestPathMB = request.getRequestPathMB();
    DispatcherType dispatcherType = DispatcherType.REQUEST;
    if (request.getDispatcherType() == DispatcherType.ASYNC) {
        dispatcherType = DispatcherType.ASYNC;
    }
    request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, dispatcherType);
    request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
    // Create the filter chain for this request
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
    // Call the filter chain for this request
    // NOTE: This also calls the servlet's service() method
    Container container = this.container;
    try {
        if ((servlet != null) && (filterChain != null)) {
            // Swallow output if needed
            if (context.getSwallowOutput()) {
                try {
                    SystemLogHandler.startCapture();
                    if (request.isAsyncDispatching()) {
                        request.getAsyncContextInternal().doInternalDispatch();
                    } else {
                        filterChain.doFilter(request.getRequest(), response.getResponse());
                    }
                } finally {
                    String log = SystemLogHandler.stopCapture();
                    if (log != null && log.length() > 0) {
                        context.getLogger().info(log);
                    }
                }
            } else {
                if (request.isAsyncDispatching()) {
                    request.getAsyncContextInternal().doInternalDispatch();
                } else {
                    filterChain.doFilter(request.getRequest(), response.getResponse());
                }
            }
        }
    } catch (ClientAbortException | CloseNowException e) {
        if (container.getLogger().isDebugEnabled()) {
            container.getLogger().debug(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        }
        throwable = e;
        exception(request, response, e);
    } catch (IOException e) {
        container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        throwable = e;
        exception(request, response, e);
    } catch (UnavailableException e) {
        container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        // throwable = e;
        // exception(request, response, e);
        wrapper.unavailable(e);
        long available = wrapper.getAvailable();
        if ((available > 0L) && (available < Long.MAX_VALUE)) {
            response.setDateHeader("Retry-After", available);
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        } else if (available == Long.MAX_VALUE) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
        }
    // Do not save exception in 'throwable', because we
    // do not want to do exception(request, response, e) processing
    } catch (ServletException e) {
        Throwable rootCause = StandardWrapper.getRootCause(e);
        if (!(rootCause instanceof ClientAbortException)) {
            container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), context.getName(), e.getMessage()), rootCause);
        }
        throwable = e;
        exception(request, response, e);
    } catch (Throwable e) {
        ExceptionUtils.handleThrowable(e);
        container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        throwable = e;
        exception(request, response, e);
    } finally {
        // Release the filter chain (if any) for this request
        if (filterChain != null) {
            filterChain.release();
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        // unload it and release this instance
        try {
            if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
            if (throwable == null) {
                exception(request, response, e);
            }
        }
        long t2 = System.currentTimeMillis();
        long time = t2 - t1;
        processingTime += time;
        if (time > maxTime) {
            maxTime = time;
        }
        if (time < minTime) {
            minTime = time;
        }
    }
}
Also used : Context(org.apache.catalina.Context) UnavailableException(jakarta.servlet.UnavailableException) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) IOException(java.io.IOException) ServletException(jakarta.servlet.ServletException) Container(org.apache.catalina.Container) CloseNowException(org.apache.coyote.CloseNowException) Servlet(jakarta.servlet.Servlet) ClientAbortException(org.apache.catalina.connector.ClientAbortException) DispatcherType(jakarta.servlet.DispatcherType)

Example 4 with CloseNowException

use of org.apache.coyote.CloseNowException in project tomcat by apache.

the class Http11InputBuffer method fill.

// --------------------------------------------------------- Private Methods
/**
 * Attempts to read some data into the input buffer.
 *
 * @return <code>true</code> if more data was added to the input buffer
 *         otherwise <code>false</code>
 */
private boolean fill(boolean block) throws IOException {
    if (log.isDebugEnabled()) {
        log.debug("Before fill(): parsingHeader: [" + parsingHeader + "], parsingRequestLine: [" + parsingRequestLine + "], parsingRequestLinePhase: [" + parsingRequestLinePhase + "], parsingRequestLineStart: [" + parsingRequestLineStart + "], byteBuffer.position(): [" + byteBuffer.position() + "], byteBuffer.limit(): [" + byteBuffer.limit() + "], end: [" + end + "]");
    }
    if (parsingHeader) {
        if (byteBuffer.limit() >= headerBufferSize) {
            if (parsingRequestLine) {
                // Avoid unknown protocol triggering an additional error
                request.protocol().setString(Constants.HTTP_11);
            }
            throw new IllegalArgumentException(sm.getString("iib.requestheadertoolarge.error"));
        }
    } else {
        byteBuffer.limit(end).position(end);
    }
    int nRead = -1;
    int mark = byteBuffer.position();
    try {
        if (byteBuffer.position() < byteBuffer.limit()) {
            byteBuffer.position(byteBuffer.limit());
        }
        byteBuffer.limit(byteBuffer.capacity());
        SocketWrapperBase<?> socketWrapper = this.wrapper;
        if (socketWrapper != null) {
            nRead = socketWrapper.read(block, byteBuffer);
        } else {
            throw new CloseNowException(sm.getString("iib.eof.error"));
        }
    } finally {
        // https://bz.apache.org/bugzilla/show_bug.cgi?id=65677
        if (byteBuffer.position() >= mark) {
            // // Position and mark are consistent. Assume a read (possibly
            // of zero bytes) has occurred.
            byteBuffer.limit(byteBuffer.position());
            byteBuffer.position(mark);
        } else {
            // Position and mark are inconsistent. Set position and limit to
            // zero so effectively no data is reported as read.
            byteBuffer.position(0);
            byteBuffer.limit(0);
        }
    }
    if (log.isDebugEnabled()) {
        log.debug("Received [" + new String(byteBuffer.array(), byteBuffer.position(), byteBuffer.remaining(), StandardCharsets.ISO_8859_1) + "]");
    }
    if (nRead > 0) {
        return true;
    } else if (nRead == -1) {
        throw new EOFException(sm.getString("iib.eof.error"));
    } else {
        return false;
    }
}
Also used : CloseNowException(org.apache.coyote.CloseNowException) EOFException(java.io.EOFException)

Aggregations

CloseNowException (org.apache.coyote.CloseNowException)4 IOException (java.io.IOException)3 DispatcherType (jakarta.servlet.DispatcherType)1 Servlet (jakarta.servlet.Servlet)1 ServletException (jakarta.servlet.ServletException)1 UnavailableException (jakarta.servlet.UnavailableException)1 EOFException (java.io.EOFException)1 Container (org.apache.catalina.Container)1 Context (org.apache.catalina.Context)1 ClientAbortException (org.apache.catalina.connector.ClientAbortException)1 MessageBytes (org.apache.tomcat.util.buf.MessageBytes)1