View | Details | Raw Unified | Return to bug 63003
Collapse All | Expand All

(-)java/org/apache/catalina/core/AsyncContextImpl.java (+14 lines)
Lines 111-116 Link Here
111
        } finally {
111
        } finally {
112
            context.fireRequestDestroyEvent(request.getRequest());
112
            context.fireRequestDestroyEvent(request.getRequest());
113
            clearServletRequestResponse();
113
            clearServletRequestResponse();
114
            this.context.decrementInProgressAsyncCount();
114
            context.unbind(Globals.IS_SECURITY_ENABLED, oldCL);
115
            context.unbind(Globals.IS_SECURITY_ENABLED, oldCL);
115
        }
116
        }
116
    }
117
    }
Lines 205-210 Link Here
205
                    request, applicationDispatcher, servletRequest, servletResponse);
206
                    request, applicationDispatcher, servletRequest, servletResponse);
206
            this.request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCH, null);
207
            this.request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCH, null);
207
            clearServletRequestResponse();
208
            clearServletRequestResponse();
209
            this.context.decrementInProgressAsyncCount();
208
        }
210
        }
209
    }
211
    }
210
212
Lines 311-316 Link Here
311
                    ActionCode.ASYNC_START, this);
313
                    ActionCode.ASYNC_START, this);
312
314
313
            this.context = context;
315
            this.context = context;
316
            context.incrementInProgressAsyncCount();
314
            this.servletRequest = request;
317
            this.servletRequest = request;
315
            this.servletResponse = response;
318
            this.servletResponse = response;
316
            this.hasOriginalRequestAndResponse = originalRequestResponse;
319
            this.hasOriginalRequestAndResponse = originalRequestResponse;
Lines 377-382 Link Here
377
    }
380
    }
378
381
379
382
383
384
    @Override
385
    public boolean isAvailable() {
386
        Context context = this.context;
387
        if (context == null) {
388
            return false;
389
        }
390
        return context.getState().isAvailable();
391
    }
392
393
380
    public void setErrorState(Throwable t, boolean fireOnError) {
394
    public void setErrorState(Throwable t, boolean fireOnError) {
381
        if (t!=null) request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
395
        if (t!=null) request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
382
        request.getCoyoteRequest().action(ActionCode.ASYNC_ERROR, null);
396
        request.getCoyoteRequest().action(ActionCode.ASYNC_ERROR, null);
(-)java/org/apache/catalina/core/StandardContext.java (+30 lines)
Lines 820-829 Link Here
820
820
821
    private boolean allowMultipleLeadingForwardSlashInPath = false;
821
    private boolean allowMultipleLeadingForwardSlashInPath = false;
822
822
823
    private final AtomicLong inProgressAsyncCount = new AtomicLong(0);
823
824
825
824
    // ----------------------------------------------------- Context Properties
826
    // ----------------------------------------------------- Context Properties
825
827
826
    @Override
828
    @Override
829
    public void incrementInProgressAsyncCount() {
830
        inProgressAsyncCount.incrementAndGet();
831
    }
832
833
834
    @Override
835
    public void decrementInProgressAsyncCount() {
836
        inProgressAsyncCount.decrementAndGet();
837
    }
838
839
840
    @Override
827
    public void setAllowMultipleLeadingForwardSlashInPath(
841
    public void setAllowMultipleLeadingForwardSlashInPath(
828
            boolean allowMultipleLeadingForwardSlashInPath) {
842
            boolean allowMultipleLeadingForwardSlashInPath) {
829
        this.allowMultipleLeadingForwardSlashInPath = allowMultipleLeadingForwardSlashInPath;
843
        this.allowMultipleLeadingForwardSlashInPath = allowMultipleLeadingForwardSlashInPath;
Lines 5325-5330 Link Here
5325
            broadcaster.sendNotification(notification);
5339
            broadcaster.sendNotification(notification);
5326
        }
5340
        }
5327
5341
5342
        // Context has been removed from Mapper at this point (so no new
5343
        // requests will be mapped) but is still available.
5344
5345
        // Give the in progress async requests a chance to complete
5346
        long limit = System.currentTimeMillis() + unloadDelay;
5347
        while (inProgressAsyncCount.get() > 0 && System.currentTimeMillis() < limit) {
5348
            try {
5349
                Thread.sleep(50);
5350
            } catch (InterruptedException e) {
5351
                // TODO
5352
                log.info(sm.getString(""), e);
5353
            }
5354
        }
5355
5356
        // Once the state is set to STOPPING, the Context will report itself as
5357
        // not available and any in progress async requests will timeout
5328
        setState(LifecycleState.STOPPING);
5358
        setState(LifecycleState.STOPPING);
5329
5359
5330
        // Binding thread
5360
        // Binding thread
(-)java/org/apache/catalina/startup/FailedContext.java (+5 lines)
Lines 809-812 Link Here
809
    }
809
    }
810
    @Override
810
    @Override
811
    public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; }
811
    public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; }
812
813
    @Override
814
    public void incrementInProgressAsyncCount() { /* NO-OP */ }
815
    @Override
816
    public void decrementInProgressAsyncCount() { /* NO-OP */ }
812
}
817
}
(-)java/org/apache/catalina/Context.java (+6 lines)
Lines 1863-1866 Link Here
1863
     *         otherwise <code>false</code>
1863
     *         otherwise <code>false</code>
1864
     */
1864
     */
1865
    public boolean getAllowMultipleLeadingForwardSlashInPath();
1865
    public boolean getAllowMultipleLeadingForwardSlashInPath();
1866
1867
1868
    public void incrementInProgressAsyncCount();
1869
1870
1871
    public void decrementInProgressAsyncCount();
1866
}
1872
}
(-)java/org/apache/coyote/AbstractProcessor.java (+4 lines)
Lines 639-644 Link Here
639
                if ((now - asyncStart) > asyncTimeout) {
639
                if ((now - asyncStart) > asyncTimeout) {
640
                    doTimeoutAsync();
640
                    doTimeoutAsync();
641
                }
641
                }
642
            } else if (!asyncStateMachine.isAvailable()) {
643
                // Timeout the async process if the associated web application
644
                // is no longer running.
645
                doTimeoutAsync();
642
            }
646
            }
643
        }
647
        }
644
    }
648
    }
(-)java/org/apache/coyote/AsyncContextCallback.java (-4 / +12 lines)
Lines 17-28 Link Here
17
package org.apache.coyote;
17
package org.apache.coyote;
18
18
19
/**
19
/**
20
 * Provides a mechanism for the Coyote connectors to signal to a
20
 * Provides a mechanism for the Coyote connectors to communicate with the
21
 * {@link javax.servlet.AsyncContext} implementation that an action, such as
21
 * {@link javax.servlet.AsyncContext}. It is implemented in this manner so that
22
 * firing event listeners needs to be taken. It is implemented in this manner
22
 * the org.apache.coyote package does not have a dependency on the
23
 * so that the org.apache.coyote package does not have a dependency on the
24
 * org.apache.catalina package.
23
 * org.apache.catalina package.
25
 */
24
 */
26
public interface AsyncContextCallback {
25
public interface AsyncContextCallback {
27
    public void fireOnComplete();
26
    public void fireOnComplete();
27
28
    /**
29
     * Reports if the web application associated with this async request is
30
     * available.
31
     *
32
     * @return {@code true} if the associated web application is available,
33
     *         otherwise {@code false}
34
     */
35
    public boolean isAvailable();
28
}
36
}
(-)java/org/apache/coyote/AsyncStateMachine.java (+10 lines)
Lines 483-488 Link Here
483
    }
483
    }
484
484
485
485
486
    synchronized boolean isAvailable() {
487
        if (asyncCtxt == null) {
488
            // Async processing has probably been completed in another thread.
489
            // Trigger a timeout to make sure the Processor is cleaned up.
490
            return false;
491
        }
492
        return asyncCtxt.isAvailable();
493
    }
494
495
486
    synchronized void recycle() {
496
    synchronized void recycle() {
487
        // Use lastAsyncStart to determine if this instance has been used since
497
        // Use lastAsyncStart to determine if this instance has been used since
488
        // it was last recycled. If it hasn't there is no need to recycle again
498
        // it was last recycled. If it hasn't there is no need to recycle again
(-)test/org/apache/tomcat/unittest/TesterContext.java (+5 lines)
Lines 1274-1277 Link Here
1274
    }
1274
    }
1275
    @Override
1275
    @Override
1276
    public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; }
1276
    public boolean getAllowMultipleLeadingForwardSlashInPath() { return false; }
1277
1278
    @Override
1279
    public void incrementInProgressAsyncCount() { /* NO-OP */ }
1280
    @Override
1281
    public void decrementInProgressAsyncCount() { /* NO-OP */ }
1277
}
1282
}

Return to bug 63003