On Mar 18, 2011, at 0:02 , Bram de Kruijff wrote:

> On Thu, Mar 17, 2011 at 7:22 PM, Marcel Offermans
> <[email protected]> wrote:
>> On Mar 17, 2011, at 18:17 , Bram de Kruijff wrote:
>> 
>>> running into deadlocks with service registration while refactorring
>>> HttpContext mechanism for the OpenSocial stuff and I am not sure how
>>> to deal with it. Seen it before, it has a smell but I can not pinpoint
>>> the cause and solution... Hope you can point me in the right
>>> direction. This is roughly/simplified what happens as far as I
>>> understand it (stacktrace below):
>>> 
>>> DM1 tracks service registrations of InterfaceA for ComponentX
>>> DM2 registers a service with InterfaceA
>>> DM1 invokes callback serviceAdded(ServiceA) on ComponentX (uses a lock)
>>> ComponentX invokes a method on ServiceA
>>> ServiceA registers new ServiceB with DM2, again with InterfaceA
>>> DM2 registers a service with InterfaceA
>>> DM1 invokes callback serviceAdded(ServiceA) on ComponentX (uses a lock)
>>> *DEADLOCK*
>>> 
>>> So, if you do something in a dependencycallback that thriggers (in any
>>> kind of indirect way) another service registration that results in the
>>> same callback and you do any kind of synchronization in the callback
>>> your are in for trouble because everything DM does is synchronous and
>>> framework serviceevents are as well. Fair enough I think, but how to
>>> deal with this?
>>> 
>>> 0. The design sucks.Never have service related side effects in
>>> callbacks? Seems a common enough use case though..
>> 
>> Never ever invoke another service while holding a lock. That includes 
>> talking to the dependency manager, since it will always try to directly act 
>> on anything you declare, so many times, the thread you use to define some 
>> new service will be used to register that service, invoke callbacks of 
>> components that were listening to this service, etc.
>> 
>> Not DM specific at all, in fact I yesterday patched a bug in the Felix 
>> whiteboard http bundle that did the same (in this case it was registering a 
>> servlet with the HttpService while holding a lock).
> 
> Yeah, I guessed as much as service listerners are synchronous as well.
> Still wondering if a more/inherently asynchronous model (not DM
> specific) wouldn't be more appropriate in the long run when delaing
> with massive amount of stacked services.

It would be an interesting thought experiment, that's for sure. The delay 
between services disappearing and others learning about it would become longer, 
which could lead to more problems. On the other hand, it would prevent huge 
stack traces you now sometimes get as the registration of a service triggers a 
chain reaction.

>>> 1. Handle callback logic (at least the stuff that has any service
>>> related side effects) asynchronous? Cumbersome..
>> 
>> Indeed, you end up launching massive amount of threads for all kinds of 
>> callbacks.
> 
> I don't mind threads :) Using a centralized/managed threadpool would suffice.

For a lot of reasons, having such a thread pool and prohibiting everybody from 
creating threads themselves is a good idea. Again, not something I can depend 
on in the DM in general.

However, it might not be too difficult to implement, as you can make your own 
dependencies. So if you create an AsynchronousServiceDependency that does not 
immediately notify the component it belongs to that some service has become 
available but instead creates a task for that and pushes it onto the scheduler, 
that could work.

Interesting things might start happening though when the order of such events 
can no longer be guaranteed. That would definitely break a lot of systems! :)

>>> 2. Make DM do stuff asynchronous.. why is it all synchronous? I guess
>>> you could get the same scenario with bare OSGi service listeners.
>> 
>> It's synchronous because I don't want to start new threads or use thread 
>> pools all over the place. That would only slow things down and even if I 
>> would make things asynchronous, I can never assume everything uses DM.
>> 
>> So in the end I think you need to be very defensive about what you do while 
>> holding a lock. In general I would say don't ever invoke something 
>> "external" to your class (especially if you cannot oversee what that 
>> external component will do).
> 
> Sounds like good advice for now :)

It's either that or move to Erlang, or some other language that has more 
fundamental support for threading and concurrency. :)

Greetings, Marcel


_______________________________________________
Amdatu-developers mailing list
[email protected]
http://lists.amdatu.org/mailman/listinfo/amdatu-developers

Reply via email to