Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 10522 invoked from network); 1 Oct 2007 07:18:57 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 1 Oct 2007 07:18:57 -0000 Received: (qmail 82387 invoked by uid 500); 1 Oct 2007 07:18:47 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 82361 invoked by uid 500); 1 Oct 2007 07:18:47 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 82350 invoked by uid 99); 1 Oct 2007 07:18:47 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Oct 2007 00:18:47 -0700 X-ASF-Spam-Status: No, hits=-98.8 required=10.0 tests=ALL_TRUSTED,DNS_FROM_DOB,RCVD_IN_DOB X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 01 Oct 2007 07:18:56 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 4327A1A9832; Mon, 1 Oct 2007 00:18:06 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r580873 - /felix/trunk/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java Date: Mon, 01 Oct 2007 07:18:05 -0000 To: commits@felix.apache.org From: fmeschbe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20071001071806.4327A1A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: fmeschbe Date: Mon Oct 1 00:17:51 2007 New Revision: 580873 URL: http://svn.apache.org/viewvc?rev=580873&view=rev Log: FELIX-384 Possible deadlock on framework startlevel change Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java Modified: felix/trunk/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java URL: http://svn.apache.org/viewvc/felix/trunk/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java?rev=580873&r1=580872&r2=580873&view=diff ============================================================================== --- felix/trunk/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java (original) +++ felix/trunk/scr/src/main/java/org/apache/felix/scr/AbstractComponentManager.java Mon Oct 1 00:17:51 2007 @@ -299,75 +299,90 @@ * 4. Call the activate method, if present * [5. Register provided services] */ - private synchronized void activateInternal() + private void activateInternal() { - // CONCURRENCY NOTE: This method is only called from within the - // ComponentActorThread to enable, activate or reactivate the - // component. Still we use the setStateConditional to not create - // a race condition with the deactivateInternal method - if ( !setStateConditional( STATE_ENABLED | STATE_UNSATISFIED, STATE_ACTIVATING ) ) - { - return; - } - - // we cannot activate if the component activator is shutting down - if ( !isActive() ) - { - getActivator().log( LogService.LOG_DEBUG, - "Component cannot be activated because the Activator is being disposed", m_componentMetadata, null ); - setState( STATE_UNSATISFIED ); - return; - } - - getActivator().log( LogService.LOG_DEBUG, "Activating component", m_componentMetadata, null ); + synchronized (this) { + // CONCURRENCY NOTE: This method is only called from within the + // ComponentActorThread to enable, activate or reactivate the + // component. Still we use the setStateConditional to not create + // a race condition with the deactivateInternal method + if ( !setStateConditional( STATE_ENABLED | STATE_UNSATISFIED, STATE_ACTIVATING ) ) + { + return; + } - // Before creating the implementation object, we are going to - // test if all the mandatory dependencies are satisfied - Iterator it = m_dependencyManagers.iterator(); - while ( it.hasNext() ) - { - DependencyManager dm = ( DependencyManager ) it.next(); - if ( !dm.isSatisfied() ) + // we cannot activate if the component activator is shutting down + if ( !isActive() ) { - // at least one dependency is not satisfied - getActivator().log( LogService.LOG_INFO, "Dependency not satisfied: " + dm.getName(), - m_componentMetadata, null ); + getActivator().log( LogService.LOG_DEBUG, + "Component cannot be activated because the Activator is being disposed", m_componentMetadata, null ); setState( STATE_UNSATISFIED ); + return; } - - // if at least one dependency is missing, we cannot continue and - // have to return - if (getState() == STATE_UNSATISFIED) + + getActivator().log( LogService.LOG_DEBUG, "Activating component", m_componentMetadata, null ); + + // Before creating the implementation object, we are going to + // test if all the mandatory dependencies are satisfied + Iterator it = m_dependencyManagers.iterator(); + while ( it.hasNext() ) { - return; + DependencyManager dm = ( DependencyManager ) it.next(); + if ( !dm.isSatisfied() ) + { + // at least one dependency is not satisfied + getActivator().log( LogService.LOG_INFO, "Dependency not satisfied: " + dm.getName(), + m_componentMetadata, null ); + setState( STATE_UNSATISFIED ); + } + + // if at least one dependency is missing, we cannot continue and + // have to return + if (getState() == STATE_UNSATISFIED) + { + return; + } } - } - // 1. Load the component implementation class - // 2. Create the component instance and component context - // 3. Bind the target services - // 4. Call the activate method, if present - if ( !createComponent() ) - { - // component creation failed, not active now - getActivator().log( LogService.LOG_ERROR, "Component instance could not be created, activation failed", - m_componentMetadata, null ); + // 1. Load the component implementation class + // 2. Create the component instance and component context + // 3. Bind the target services + // 4. Call the activate method, if present + if ( !createComponent() ) + { + // component creation failed, not active now + getActivator().log( LogService.LOG_ERROR, "Component instance could not be created, activation failed", + m_componentMetadata, null ); + + // set state to unsatisfied + setState( STATE_UNSATISFIED ); - // set state to unsatisfied - setState( STATE_UNSATISFIED ); + return; + } - return; + // Validation occurs before the services are provided, otherwhise the + // service provider's service may be called by a service requester + // while it is still ACTIVATING + setState( getSatisfiedState() ); } - // Validation occurs before the services are provided, otherwhise the - // service provider's service may be called by a service requester - // while it is still ACTIVATING - setState( getSatisfiedState() ); - // 5. Register provided services - m_serviceRegistration = registerComponentService(); + // call this outside of the synchronization to prevent a possible + // deadlock if service registration tries to lock the framework or + // owning bundle during registration (see FELIX-384) + try + { + m_serviceRegistration = registerComponentService(); + getActivator().log( LogService.LOG_DEBUG, "Component activated", m_componentMetadata, null ); + } + catch ( IllegalStateException ise ) + { + // thrown by service registration if the bundle is stopping + // we just log this at debug level but ignore it + getActivator().log( LogService.LOG_DEBUG, "Component activation failed while registering the service", + m_componentMetadata, ise ); + } - getActivator().log( LogService.LOG_DEBUG, "Component activated", m_componentMetadata, null ); } @@ -466,7 +481,7 @@ * Method is called by {@link #activate()} in STATE_ACTIVATING or by * {@link DelayedComponentManager#getService(Bundle, ServiceRegistration)} * in STATE_REGISTERED. - * + * * @return true if creation of the component succeeded. If * false is returned, the cause should have been logged. */ @@ -679,7 +694,7 @@ * Otherwise the state is not changed and false is returned. *

* This method atomically checks the current state and sets the new state. - * + * * @param requiredStates The set of states required for the state change to * happen. * @param newState The new state to go into.