What should be done when a BundleActivator
runs a background thread, and that background thread has an unrecoverable error?
public class Activator implements BundleActivator
{
private Thread t;
@Override
public void start(BundleContext context) throws Exception
{
t = new Thread(new Runnable(){
@Override
public void run(){
while (!Thread.interrupted()){
// do something which may throw a runtime exception
}
}
});
t.start();
}
@Override void stop(BundleContext context) throws Exception
{
t.interrupt();
t.join();
}
}
With this example, how can I notify the OSGi framework that the thread is dead and the bundle is effectively stopped and not running?
Look at how Peter Kriens performs similar actions in this article. All you would need to do with his example is invoke the stop on the activator in his catch block, instead of doing the printStackTrace.
As far as I know, OSGi cannot directly help you in this particular situation. I usually rely on uncaught exception handlers to get notified of thread crashes or I implement some form of SW watchdog.
The point is that a bundle that spawns multiple threads and sucessfully completes its start method remains ACTIVE even if one of these threads crashes after some time.
Neil is (as usual) very right. A bundle should never stop itself since that interferes with the management agent. The start/stop is the message from this management agent to a bundle to say that it should be active. If the bundle cannot perform its responsibility you should log the message, wait a bit (increasingly longer) and retry.
The log is the place to notify, stopping a bundle is mixing levels badly.
Probably the best thing to do is just log the error, preferably to the OSGi Log Service. Then an administrator can detect the problem with the bundle and decide what to do. You should implement this as a Declarative Services component rather than as a
BundleActivator
, because that will give you much easier access to the Log Service, and you will also be able to have more than one of these things in your bundle.I don't think that the bundle should attempt to stop itself. This puts the bundle in a weird state.... it's stopped but still has code running... i.e. the code that called
stop()
. This may be only for a brief period but it feels wrong.A bundle that's in the ACTIVE state doesn't necessarily have to be "doing something" all the time, it just has the potential to "do something". The fact that something failed shouldn't really affect the external state of the bundle.