Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2014-02-07 14:47:28 +0000
committerThomas Watson2014-02-07 15:48:05 +0000
commit3ede3a0bb06e8ae31e993c9cc5f5429ae491e7e2 (patch)
tree358adb90caae0dfff6f640e8996ea9881fd93133
parent3760fe1be94443c4166211b533c923a887e6ba22 (diff)
downloadrt.equinox.framework-3ede3a0bb06e8ae31e993c9cc5f5429ae491e7e2.tar.gz
rt.equinox.framework-3ede3a0bb06e8ae31e993c9cc5f5429ae491e7e2.tar.xz
rt.equinox.framework-3ede3a0bb06e8ae31e993c9cc5f5429ae491e7e2.zip
Bug 391319 - bundleContext.getBundle(0).stop() does not shut down the systemI20140211-1100I20140211-0800I20140209-1458
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java36
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java92
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java72
3 files changed, 84 insertions, 116 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java
index ddb3ca82b..7a10b79cd 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/adaptor/EclipseStarter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2003, 2013 IBM Corporation and others.
+ * Copyright (c) 2003, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -17,6 +17,8 @@ import java.net.*;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.*;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
import org.eclipse.core.runtime.internal.adaptor.*;
import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.log.FrameworkLog;
@@ -400,12 +402,14 @@ public class EclipseStarter {
public static void shutdown() throws Exception {
if (!running || framework == null)
return;
- if (appLauncherRegistration != null)
- appLauncherRegistration.unregister();
- if (splashStreamRegistration != null)
- splashStreamRegistration.unregister();
- if (defaultMonitorRegistration != null)
- defaultMonitorRegistration.unregister();
+ if (framework.getState() == Bundle.ACTIVE) {
+ if (appLauncherRegistration != null)
+ appLauncherRegistration.unregister();
+ if (splashStreamRegistration != null)
+ splashStreamRegistration.unregister();
+ if (defaultMonitorRegistration != null)
+ defaultMonitorRegistration.unregister();
+ }
if (appLauncher != null)
appLauncher.shutdown();
appLauncherRegistration = null;
@@ -416,9 +420,11 @@ public class EclipseStarter {
consoleMgr.stopConsole();
consoleMgr = null;
}
- framework.stop();
- framework.waitForStop(0);
- framework = null;
+ if (framework.getState() == Bundle.ACTIVE) {
+ framework.stop();
+ framework.waitForStop(0);
+ framework = null;
+ }
configuration = null;
equinoxConfig = null;
context = null;
@@ -532,7 +538,7 @@ public class EclipseStarter {
* all basic bundles that are marked to start.
* Returns null if the framework has been shutdown as a result of refreshPackages
*/
- private static Bundle[] loadBasicBundles() {
+ private static Bundle[] loadBasicBundles() throws InterruptedException {
long startTime = System.currentTimeMillis();
String osgiBundles = getProperty(PROP_BUNDLES);
String osgiExtensions = getProperty(PROP_EXTENSIONS);
@@ -633,7 +639,7 @@ public class EclipseStarter {
}
// returns true if the refreshPackages operation caused the framework to shutdown
- private static boolean refreshPackages(Bundle[] bundles) {
+ private static boolean refreshPackages(Bundle[] bundles) throws InterruptedException {
FrameworkWiring frameworkWiring = context.getBundle().adapt(FrameworkWiring.class);
if (frameworkWiring == null)
return false;
@@ -1100,7 +1106,7 @@ public class EclipseStarter {
return relative;
}
- private static void setStartLevel(final int value) {
+ private static void setStartLevel(final int value) throws InterruptedException {
FrameworkStartLevel fwkStartLevel = context.getBundle().adapt(FrameworkStartLevel.class);
final Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.STARTLEVEL_CHANGED);
@@ -1130,7 +1136,7 @@ public class EclipseStarter {
}
- private static void updateSplash(Semaphore semaphore, StartupEventListener listener) {
+ private static void updateSplash(Semaphore semaphore, StartupEventListener listener) throws InterruptedException {
ServiceTracker<StartupMonitor, StartupMonitor> monitorTracker = new ServiceTracker<StartupMonitor, StartupMonitor>(context, StartupMonitor.class.getName(), null);
try {
monitorTracker.open();
@@ -1149,7 +1155,7 @@ public class EclipseStarter {
}
}
// can we acquire the semaphore yet?
- if (semaphore.acquire(50))
+ if (semaphore.tryAcquire(50, TimeUnit.MILLISECONDS))
break; //done
//else still working, spin another update
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java
index bd2fe63eb..5a812bf6a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/EclipseAppLauncher.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2013 IBM Corporation and others.
+ * Copyright (c) 2005, 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@ package org.eclipse.core.runtime.internal.adaptor;
import java.lang.reflect.Method;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
@@ -21,16 +22,17 @@ import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.service.runnable.*;
import org.osgi.framework.*;
+import org.osgi.framework.launch.Framework;
public class EclipseAppLauncher implements ApplicationLauncher {
volatile private ParameterizedRunnable runnable = null;
private Object appContext = null;
- private Semaphore runningLock = new Semaphore(1);
- private Semaphore waitForAppLock = new Semaphore(0);
- private BundleContext context;
+ private final java.util.concurrent.Semaphore runningLock = new java.util.concurrent.Semaphore(1);
+ private final java.util.concurrent.Semaphore waitForAppLock = new java.util.concurrent.Semaphore(0);
+ private final BundleContext context;
private boolean relaunch = false;
- private boolean failOnNoDefault = false;
- private FrameworkLog log;
+ private final boolean failOnNoDefault;
+ private final FrameworkLog log;
private final EquinoxConfiguration equinoxConfig;
public EclipseAppLauncher(BundleContext context, boolean relaunch, boolean failOnNoDefault, FrameworkLog log, EquinoxConfiguration equinoxConfig) {
@@ -75,16 +77,37 @@ public class EclipseAppLauncher implements ApplicationLauncher {
throw new IllegalStateException(Msg.ECLIPSE_STARTUP_ERROR_NO_APPLICATION);
Object result = null;
boolean doRelaunch;
+ Bundle b = context.getBundle();
do {
try {
+ if (relaunch) {
+ // need a thread to kick the main thread when the framework stops
+ final Thread mainThread = Thread.currentThread();
+ final BundleContext mainContext = context;
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ Framework framework = (Framework) mainContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION);
+ try {
+ framework.waitForStop(0);
+ // framework is done; tell the main thread to stop
+ mainThread.interrupt();
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ // just exiting now
+ }
+ }
+ }, "Framework watcher").start(); //$NON-NLS-1$
+
+ }
result = runApplication(defaultContext);
} catch (Exception e) {
- if (!relaunch || (context.getBundle().getState() & Bundle.ACTIVE) == 0)
+ if (!relaunch || (b.getState() & Bundle.ACTIVE) == 0)
throw e;
if (log != null)
log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, Msg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null));
}
- doRelaunch = (relaunch && (context.getBundle().getState() & Bundle.ACTIVE) != 0);
+ doRelaunch = (relaunch && (b.getState() & Bundle.ACTIVE) != 0);
} while (doRelaunch);
return result;
}
@@ -94,30 +117,36 @@ public class EclipseAppLauncher implements ApplicationLauncher {
* current thread (main).
*/
private Object runApplication(Object defaultContext) throws Exception {
- // wait for an application to be launched.
- waitForAppLock.acquire();
- // an application is ready; acquire the running lock.
- // this must happen after we have acquired an application (by acquiring waitForAppLock above).
- runningLock.acquire();
- if (EclipseStarter.debug) {
- String timeString = equinoxConfig.getConfiguration("eclipse.startTime"); //$NON-NLS-1$
- long time = timeString == null ? 0L : Long.parseLong(timeString);
- System.out.println("Starting application: " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
- }
try {
- // run the actual application on the current thread (main).
- return runnable.run(appContext != null ? appContext : defaultContext);
- } finally {
- // free the runnable application and release the lock to allow another app to be launched.
- runnable = null;
- appContext = null;
- runningLock.release();
+ // wait for an application to be launched.
+ waitForAppLock.acquire();
+ // an application is ready; acquire the running lock.
+ // this must happen after we have acquired an application (by acquiring waitForAppLock above).
+ runningLock.acquire();
+ if (EclipseStarter.debug) {
+ String timeString = equinoxConfig.getConfiguration("eclipse.startTime"); //$NON-NLS-1$
+ long time = timeString == null ? 0L : Long.parseLong(timeString);
+ System.out.println("Starting application: " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
+ }
+ try {
+ // run the actual application on the current thread (main).
+ return runnable.run(appContext != null ? appContext : defaultContext);
+ } finally {
+ // free the runnable application and release the lock to allow another app to be launched.
+ runnable = null;
+ appContext = null;
+ runningLock.release();
+ }
+ } catch (InterruptedException e) {
+ // ignore; but mark interrupted for others
+ Thread.interrupted();
}
+ return null;
}
public void launch(ParameterizedRunnable app, Object applicationContext) {
- waitForAppLock.acquire(-1); // clear out any pending apps notifications
- if (!runningLock.acquire(-1)) // check to see if an application is currently running
+ waitForAppLock.tryAcquire(); // clear out any pending apps notifications
+ if (!runningLock.tryAcquire()) // check to see if an application is currently running
throw new IllegalStateException("An application is aready running."); //$NON-NLS-1$
this.runnable = app;
this.appContext = applicationContext;
@@ -128,12 +157,17 @@ public class EclipseAppLauncher implements ApplicationLauncher {
public void shutdown() {
// this method will aquire and keep the runningLock to prevent
// all future application launches.
- if (runningLock.acquire(-1))
+ if (runningLock.tryAcquire())
return; // no application is currently running.
ParameterizedRunnable currentRunnable = runnable;
if (currentRunnable instanceof ApplicationRunnable) {
((ApplicationRunnable) currentRunnable).stop();
- runningLock.acquire(60000); // timeout after 1 minute.
+ try {
+ runningLock.tryAcquire(1, TimeUnit.MINUTES); // timeout after 1 minute.
+ } catch (InterruptedException e) {
+ // ignore
+ Thread.interrupted();
+ }
}
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java
deleted file mode 100644
index f017aee5e..000000000
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/core/runtime/internal/adaptor/Semaphore.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2003, 2012 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.core.runtime.internal.adaptor;
-
-/**
- * Internal class.
- */
-public class Semaphore {
- protected long notifications;
-
- public Semaphore(int count) {
- notifications = count;
- }
-
- /**
- * Attempts to acquire this semaphore. Returns only when the semaphore has been acquired.
- */
- public synchronized void acquire() {
- while (true) {
- if (notifications > 0) {
- notifications--;
- return;
- }
- try {
- wait();
- } catch (InterruptedException e) {
- //Ignore
- }
- }
- }
-
- /**
- * Attempts to acquire this semaphore. Returns true if it was successfully acquired,
- * and false otherwise.
- */
- public synchronized boolean acquire(long delay) {
- long start = System.currentTimeMillis();
- long timeLeft = delay;
- while (true) {
- if (notifications > 0) {
- notifications--;
- return true;
- }
- if (timeLeft <= 0)
- return false;
- try {
- wait(timeLeft);
- } catch (InterruptedException e) {
- //Ignore
- }
- timeLeft = start + delay - System.currentTimeMillis();
- }
- }
-
- public synchronized void release() {
- notifications++;
- notifyAll();
- }
-
- // for debug only
- public String toString() {
- return "Semaphore(" + notifications + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- }
-}

Back to the top