Author: davidb Date: Fri Feb 26 10:56:04 2016 New Revision: 1732453 URL: http://svn.apache.org/viewvc?rev=1732453&view=rev Log: FELIX-5199 Race condition in HttpServiceFactory.getService() causing exception
Improved the thread safety of this fix. Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java?rev=1732453&r1=1732452&r2=1732453&view=diff ============================================================================== --- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java (original) +++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java Fri Feb 26 10:56:04 2016 @@ -139,14 +139,27 @@ public final class HttpServiceFactory @Override public HttpService getService(final Bundle bundle, final ServiceRegistration<HttpService> reg) { - if ( active ) { - return new PerBundleHttpServiceImpl(bundle, - this.sharedHttpService, - this.context, - this.contextAttributeListenerManager, - this.sharedContextAttributes, - this.requestListenerManager, - this.requestAttributeListenerManager); + // Only return a service after start() has been called. + if (active) { + // Store everything that we want to pass to the PerBundleHttpServiceImpl in local vars to avoid + // a race condition where the service might be stopped while this method is executing. + SharedHttpServiceImpl sharedHttpSvc = this.sharedHttpService; + ServletContext servletCtx = this.context; + ServletContextAttributeListenerManager servletCtxAttrListenerMgr = this.contextAttributeListenerManager; + boolean sharedCtxAttrs = this.sharedContextAttributes; + ServletRequestListenerManager reqListenerMgr = this.requestListenerManager; + ServletRequestAttributeListenerManager reqAttrListenerMgr = this.requestAttributeListenerManager; + + if ( active ) { + // Only return the service if we're still active + return new PerBundleHttpServiceImpl(bundle, + sharedHttpSvc, + servletCtx, + servletCtxAttrListenerMgr, + sharedCtxAttrs, + reqListenerMgr, + reqAttrListenerMgr); + } } return null; }