Right. I suppose I can enhance my BaseManagedServiceFactory the following way https://gist.github.com/2786874 It will wait for a certain amount of time before interrupting the threads, which should get rid of the deadlock in case it happens.
I think I'll put that class in the utils project so that other people can benefit from it. On Fri, May 25, 2012 at 10:57 AM, Felix Meschberger <[email protected]> wrote: > Hi, > > Am 24.05.2012 um 18:18 schrieb Guillaume Nodet: > >> ... which makes me thing that being able to register services (or at >> least try) while the bundle is stopping is still wrong. >> What's the use case for that ? > > I agree it is arguable, but the core spec states in Section 5.2.3, > Registering Services : > >> The Framework permits bundles to register and unregister service objects >> dynamically. Therefore, a bundle is permitted to register service objects at >> any time during the STARTING, ACTIVE or STOPPING states. > > So, it must be possible. > > Regards > Felix > > >> >> On Thu, May 24, 2012 at 6:05 PM, Guillaume Nodet <[email protected]> wrote: >>> That's actually a really good idea. >>> For the record, I came up with the following class >>> https://gist.github.com/2782423 >>> which can't prevent all deadlocks (I think there's still a small >>> window of time where the service registration could be attempted while >>> the bundle lock is grabbed by the framework when stopping the bundle, >>> but before the factory destroy() method is called), but it's way >>> better. >>> Though, the mere fact I don't see a nice way to avoid the deadlock >>> kinda bothers me. >>> >>> On Thu, May 24, 2012 at 3:58 PM, Marcel Offermans >>> <[email protected]> wrote: >>>> Another pattern you could use here is to have the updated method only >>>> validate if the configuration it received is valid and not process it at >>>> all in the updated method but delegate that to a different method. That >>>> way, you can probably even prevent the creation of the objects you mention >>>> in your example altogether. Of course there then has to be "something >>>> else" to delegate to (like some other thread). >>>> >>>> Greetings, Marcel >>>> >>>> >>>> On May 24, 2012, at 15:37 PM, Felix Meschberger wrote: >>>> >>>>> Hi, >>>>> >>>>> Am 24.05.2012 um 15:29 schrieb Guillaume Nodet: >>>>> >>>>>> The assumptions are right. >>>>>> >>>>>> Do you have any pointer to a well written ManagedServiceFactory that >>>>>> can make sure calls to updates are finished before destroying the >>>>>> ManagedServiceFactory without any synchronized blocks ? >>>>> >>>>> Not, off the top of my head. >>>>> >>>>> I think it is not possible to fully synchronized (ok you could Java 5 >>>>> locks which may time out, but after a timeout there is no guarantee, >>>>> either). >>>>> >>>>> I think the best thing that can be done, is that shutting down a >>>>> ManagedServiceFactory must just be made lenient. >>>>> >>>>> For example, consider a MSF.updated method creates some object and adds >>>>> it to a table in the MSF class. When stopping the MSF you start by >>>>> setting a "stopped" flag and then cleanup all objects in the table. In >>>>> the updated method you check the stopped flag on entry and only add the >>>>> generated object to the table at the very end of updated after an >>>>> additional check for the stopped flag. If the flag is set at that point >>>>> in time, cleanup the object just created instead of adding it to the >>>>> table. >>>>> >>>>> Usually, I do work with such a "stopped" flag preventing further >>>>> concurrent operation. >>>>> >>>>> Regards >>>>> Felix >>>>> >>>>>> >>>>>> On Thu, May 24, 2012 at 3:20 PM, Felix Meschberger <[email protected]> >>>>>> wrote: >>>>>>> Hi, >>>>>>> >>>>>>> >>>>>>> Am 24.05.2012 um 12:09 schrieb Guillaume Nodet: >>>>>>> >>>>>>>> I have the following deadlock that sometimes happen: >>>>>>>> >>>>>>>> Thread 1: >>>>>>> >>>>>>>> start the bundle >>>>>>>> register a ManagedServiceFactory >>>>>>> >>>>>>> Assumption: Thread 1 has finished processing when Thread 2 and 3 start >>>>>>> with their processing >>>>>>> >>>>>>>> >>>>>>>> Thread 2: >>>>>>>> stop the bundle >>>>>>> >>>>>>> Assumption: This followin code runs in the BundleActivator.stop method. >>>>>>> >>>>>>>> grab the bundle lock >>>>>>>> try to destroy the ManagedServiceFactory >>>>>>>> deadlock on grabbing the ManagedServiceFactory lock >>>>>>>> >>>>>>>> Thread 3: >>>>>>> >>>>>>> Assumption: This is the CM_Update thread calling back due to Thread 1's >>>>>>> service registration. >>>>>>> >>>>>>>> in a different thread, the ConfigAdmin will call the >>>>>>>> ManagedServiceFactory#update() >>>>>>>> enter synchronized block in the ManagedServiceFactory >>>>>>>> register a service >>>>>>>> try to grab the bundle lock >>>>>>>> >>>>>>>> >>>>>>>> I don't think the problem comes from my ManagedServiceFactory, as it >>>>>>>> has to be synchronized in order for the destruction of the >>>>>>>> ManagedServiceFactory to make sure we destroy all the previously >>>>>>>> created services. >>>>>>> >>>>>>> I disagree. >>>>>>> >>>>>>> I think you are violating the recommendations in section 4.7.3, >>>>>>> Synchronization Pitfalls, in the Core Spec. >>>>>>> >>>>>>> Regards >>>>>>> Felix >>>>>>> >>>>>>>> >>>>>>>> It seems to me that the problem comes from FELIX-3082 which allows the >>>>>>>> registration of services while the bundle is stopping. >>>>>>>> I think if we remove that bit, the third thread will reject the >>>>>>>> service registration, exit the ManagedServiceFactory#update() and >>>>>>>> release the ManagedServiceFactory lock. >>>>>>>> >>>>>>>> I'll give it a try, but thoughts are welcomed. >>>>>>>> >>>>>>>> -- >>>>>>>> ------------------------ >>>>>>>> Guillaume Nodet >>>>>>>> ------------------------ >>>>>>>> Blog: http://gnodet.blogspot.com/ >>>>>>>> ------------------------ >>>>>>>> FuseSource, Integration everywhere >>>>>>>> http://fusesource.com >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> ------------------------ >>>>>> Guillaume Nodet >>>>>> ------------------------ >>>>>> Blog: http://gnodet.blogspot.com/ >>>>>> ------------------------ >>>>>> FuseSource, Integration everywhere >>>>>> http://fusesource.com >>>>> >>>>> >>>>> >>>> >>> >>> >>> >>> -- >>> ------------------------ >>> Guillaume Nodet >>> ------------------------ >>> Blog: http://gnodet.blogspot.com/ >>> ------------------------ >>> FuseSource, Integration everywhere >>> http://fusesource.com >> >> >> >> -- >> ------------------------ >> Guillaume Nodet >> ------------------------ >> Blog: http://gnodet.blogspot.com/ >> ------------------------ >> FuseSource, Integration everywhere >> http://fusesource.com > -- ------------------------ Guillaume Nodet ------------------------ Blog: http://gnodet.blogspot.com/ ------------------------ FuseSource, Integration everywhere http://fusesource.com
