You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@felix.apache.org by jgunz <sl...@twcny.rr.com> on 2009/06/09 18:59:05 UTC

Deadlock registering service

I'm trying to register a service in a thread spawned from an
Activator.start() method but the call is deadlocking. If I make the same
calls within the start() thread it works fine. Should the following work?

    public void start(final BundleContext bundleContext) throws Exception
    {
        Thread bundleStartupThread = new Thread(new Runnable(){
            public void run()
            {
                    Hashtable properties = new Hashtable();
                    properties.put(
                       Constants.SERVICE_PID,
                        "foo.bar");
                    bundleContext.registerService(Integer.class.getName(),
new Integer(4) , properties);
                    
            }
        });

        bundleStartupThread.start();
    }

-- 
View this message in context: http://www.nabble.com/Deadlock-registering-service-tp23947039p23947039.html
Sent from the Apache Felix - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Deadlock registering service

Posted by "Richard S. Hall" <he...@ungoverned.org>.
You might be closer if you let the calling thread return and then spawn 
two new threads, one to register the service and one to monitor the 
thread registering the service. However, it is not clear that the spec 
requires the framework to make calls interruptible or not, so it may not 
be possible to do this in a consistent way across framework implementations.

-> richard

On 6/9/09 3:43 PM, jgunz wrote:
> Thank you for the explanation, it was very helpful.
>    

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Deadlock registering service

Posted by jgunz <sl...@twcny.rr.com>.
Thank you for the explanation, it was very helpful. 
-- 
View this message in context: http://www.nabble.com/Deadlock-registering-service-tp23947039p23950042.html
Sent from the Apache Felix - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Deadlock registering service

Posted by "Richard S. Hall" <he...@ungoverned.org>.
On 6/9/09 3:27 PM, Richard S. Hall wrote:
> A bundle that is starting is in the middle of a state change (i.e., 
> RESOLVED->STARTING->ACTIVE), so the framework must hold a lock on that 
> bundle to ensure its state isn't messed with externally why it is in 
> the process of starting.

That should say, "...while it is in the process of starting."

-> richard

> So, when the activator start() method is called, the thread holds a 
> lock for the bundle being started.
>
> When a bundle registers a service, this is also state sensitive, since 
> a bundle can only register a service while it is active. Thus, this 
> requires that we hold a lock on the bundle until the service is 
> registered.
>
> Given your scenario, you have the calling thread holding the bundle 
> lock and the registering thread wanting the bundle lock, so deadlock.
>
> In general, it is not a good thing to spawn another thread which calls 
> back into the framework while blocking the original thread.
>
> -> richard
>
> On 6/9/09 2:53 PM, jgunz wrote:
>> You're absolutely correct. I oversimplified my use case and made one 
>> that
>> worked. Below is what I'm really trying to do, and I verified it does
>> deadlock this time. I'm trying to make a safe wrapper around 
>> BundleActivator
>> that makes sure developers don't block in the start() method 
>> indefinitely so
>> we can more quickly diagnose problems during development...
>>
>>
>> public final static long bundleStartupTimeoutInSeconds = 15;
>>
>> public void start(final BundleContext bundleContext) throws Exception
>> {
>>          final Semaphore bundleStartedSemaphore = new Semaphore(1);
>>          bundleStartedSemaphore.acquire();
>>
>>          Thread bundleStartupThread = new Thread(new Runnable(){
>>              public void run()
>>              {
>>                  try
>>                  {
>>                      Hashtable properties = new Hashtable();
>>                      properties.put(Constants.SERVICE_PID,"foo.bar");
>>                      
>> bundleContext.registerService(Integer.class.getName(),
>> new Integer(4) , properties);
>>
>>                      bundleStartedSemaphore.release();
>>                  }
>>                  catch(Throwable t)
>>                  {
>>                      t.printStackTrace();
>>                  }
>>              }
>>          });
>>
>>          bundleStartupThread.start();
>>
>>          
>> if(!bundleStartedSemaphore.tryAcquire(bundleStartupTimeoutInSeconds,
>> TimeUnit.SECONDS))
>>          {
>>              bundleStartupThread.interrupt();
>>
>>              String message =
>>                  "Bundle start-up timeout exceeded
>> ("+bundleStartupTimeoutInSeconds+" secs) " +
>>                  "when starting bundle
>> '"+bundleContext.getBundle().getSymbolicName()+"'.";
>>
>>              throw new TimeoutException(message);
>>          }
>> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Deadlock registering service

Posted by "Richard S. Hall" <he...@ungoverned.org>.
A bundle that is starting is in the middle of a state change (i.e., 
RESOLVED->STARTING->ACTIVE), so the framework must hold a lock on that 
bundle to ensure its state isn't messed with externally why it is in the 
process of starting. So, when the activator start() method is called, 
the thread holds a lock for the bundle being started.

When a bundle registers a service, this is also state sensitive, since a 
bundle can only register a service while it is active. Thus, this 
requires that we hold a lock on the bundle until the service is registered.

Given your scenario, you have the calling thread holding the bundle lock 
and the registering thread wanting the bundle lock, so deadlock.

In general, it is not a good thing to spawn another thread which calls 
back into the framework while blocking the original thread.

-> richard

On 6/9/09 2:53 PM, jgunz wrote:
> You're absolutely correct. I oversimplified my use case and made one that
> worked. Below is what I'm really trying to do, and I verified it does
> deadlock this time. I'm trying to make a safe wrapper around BundleActivator
> that makes sure developers don't block in the start() method indefinitely so
> we can more quickly diagnose problems during development...
>
>
> public final static long bundleStartupTimeoutInSeconds = 15;
>
> public void start(final BundleContext bundleContext) throws Exception
> {
>          final Semaphore bundleStartedSemaphore = new Semaphore(1);
>          bundleStartedSemaphore.acquire();
>
>          Thread bundleStartupThread = new Thread(new Runnable(){
>              public void run()
>              {
>                  try
>                  {
>                      Hashtable properties = new Hashtable();
>                      properties.put(Constants.SERVICE_PID,"foo.bar");
>                      bundleContext.registerService(Integer.class.getName(),
> new Integer(4) , properties);
>
>                      bundleStartedSemaphore.release();
>                  }
>                  catch(Throwable t)
>                  {
>                      t.printStackTrace();
>                  }
>              }
>          });
>
>          bundleStartupThread.start();
>
>          if(!bundleStartedSemaphore.tryAcquire(bundleStartupTimeoutInSeconds,
> TimeUnit.SECONDS))
>          {
>              bundleStartupThread.interrupt();
>
>              String message =
>                  "Bundle start-up timeout exceeded
> ("+bundleStartupTimeoutInSeconds+" secs) " +
>                  "when starting bundle
> '"+bundleContext.getBundle().getSymbolicName()+"'.";
>
>              throw new TimeoutException(message);
>          }
> }
>    

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Deadlock registering service

Posted by jgunz <sl...@twcny.rr.com>.
You're absolutely correct. I oversimplified my use case and made one that
worked. Below is what I'm really trying to do, and I verified it does
deadlock this time. I'm trying to make a safe wrapper around BundleActivator
that makes sure developers don't block in the start() method indefinitely so
we can more quickly diagnose problems during development...


public final static long bundleStartupTimeoutInSeconds = 15;

public void start(final BundleContext bundleContext) throws Exception
{
        final Semaphore bundleStartedSemaphore = new Semaphore(1);
        bundleStartedSemaphore.acquire();
            
        Thread bundleStartupThread = new Thread(new Runnable(){
            public void run()
            {
                try
                {
                    Hashtable properties = new Hashtable();
                    properties.put(Constants.SERVICE_PID,"foo.bar");
                    bundleContext.registerService(Integer.class.getName(),
new Integer(4) , properties);

                    bundleStartedSemaphore.release();
                }
                catch(Throwable t)
                {
                    t.printStackTrace();
                }
            }
        });

        bundleStartupThread.start();

        if(!bundleStartedSemaphore.tryAcquire(bundleStartupTimeoutInSeconds,
TimeUnit.SECONDS))
        {
            bundleStartupThread.interrupt();
            
            String message =
                "Bundle start-up timeout exceeded
("+bundleStartupTimeoutInSeconds+" secs) " +
                "when starting bundle
'"+bundleContext.getBundle().getSymbolicName()+"'.";
            
            throw new TimeoutException(message);
        }
}
-- 
View this message in context: http://www.nabble.com/Deadlock-registering-service-tp23947039p23949183.html
Sent from the Apache Felix - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: Deadlock registering service

Posted by Stuart McCulloch <mc...@gmail.com>.
2009/6/10 jgunz <sl...@twcny.rr.com>

>
> I'm trying to register a service in a thread spawned from an
> Activator.start() method but the call is deadlocking. If I make the same
> calls within the start() thread it works fine. Should the following work?
>
>    public void start(final BundleContext bundleContext) throws Exception
>    {
>        Thread bundleStartupThread = new Thread(new Runnable(){
>            public void run()
>            {
>                    Hashtable properties = new Hashtable();
>                    properties.put(
>                       Constants.SERVICE_PID,
>                        "foo.bar");
>                    bundleContext.registerService(Integer.class.getName(),
> new Integer(4) , properties);
>
>            }
>        });
>
>        bundleStartupThread.start();
>    }
>

I just pasted that exact code into a bundle and tried it out with a recent
version of Felix
and didn't see any deadlock - what version of Felix are you using, and also
could you
take a thread-dump when you get the hang and send it to the list?

Use Ctrl-Brk on Windows, Ctrl-\ on Linux if you have access to the console
window,
otherwise for Java 5 or later you can use the "jstack" utility that ships
with the JDK:

   jstack -l <pid>

HTH


> --
> View this message in context:
> http://www.nabble.com/Deadlock-registering-service-tp23947039p23947039.html
> Sent from the Apache Felix - Users mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>
-- 
Cheers, Stuart