mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 12:00:04 +02:00
fix: refresh bundles synchronously
- remove unnecessary waits during synchronous activate/deactivate
This commit is contained in:
parent
0d520dae16
commit
7f9d82fa47
3 changed files with 46 additions and 30 deletions
|
@ -19,9 +19,9 @@ import java.io.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
import org.apache.felix.framework.FrameworkFactory;
|
import org.apache.felix.framework.FrameworkFactory;
|
||||||
import org.apache.felix.framework.util.FelixConstants;
|
import org.apache.felix.framework.util.FelixConstants;
|
||||||
|
@ -520,29 +520,13 @@ public class BundleHost {
|
||||||
return frameworkBundleContext.getBundle(bundleLocation);
|
return frameworkBundleContext.getBundle(bundleLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean anyMatch(Bundle bundle, int... bundleStates) {
|
|
||||||
Integer bundleState = bundle.getState();
|
|
||||||
return IntStream.of(bundleStates).anyMatch(bundleState::equals);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void waitFor(Bundle bundle, int... bundleStates) throws InterruptedException {
|
|
||||||
while (true) {
|
|
||||||
if (anyMatch(bundle, bundleStates)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Thread.sleep(500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate a bundle, returning only after the bundle is active.
|
* Activate a bundle. Either an exception is thrown or the bundle will be in "ACTIVE" state.
|
||||||
*
|
*
|
||||||
* @param bundle the bundle
|
* @param bundle the bundle
|
||||||
* @throws InterruptedException if the wait is interrupted
|
|
||||||
* @throws GhidraBundleException if there's a problem activating
|
* @throws GhidraBundleException if there's a problem activating
|
||||||
*/
|
*/
|
||||||
public void activateSynchronously(Bundle bundle)
|
public void activateSynchronously(Bundle bundle) throws GhidraBundleException {
|
||||||
throws InterruptedException, GhidraBundleException {
|
|
||||||
if (bundle.getState() == Bundle.ACTIVE) {
|
if (bundle.getState() == Bundle.ACTIVE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -555,11 +539,10 @@ public class BundleHost {
|
||||||
fireBundleException(bundleException);
|
fireBundleException(bundleException);
|
||||||
throw bundleException;
|
throw bundleException;
|
||||||
}
|
}
|
||||||
waitFor(bundle, Bundle.ACTIVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate a bundle, returning only after the bundle is active.
|
* Activate a bundle. Either an exception is thrown or the bundle will be in "ACTIVE" state.
|
||||||
*
|
*
|
||||||
* @param bundleLocation the bundle location identifier
|
* @param bundleLocation the bundle location identifier
|
||||||
* @throws InterruptedException if the wait is interrupted
|
* @throws InterruptedException if the wait is interrupted
|
||||||
|
@ -575,14 +558,12 @@ public class BundleHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate a bundle, returning only after the bundle is inactive.
|
* Deactivate a bundle. Either an exception is thrown or the bundle will be in "UNINSTALLED" state.
|
||||||
*
|
*
|
||||||
* @param bundle the bundle
|
* @param bundle the bundle
|
||||||
* @throws InterruptedException if the wait is interrupted
|
|
||||||
* @throws GhidraBundleException if there's a problem activating
|
* @throws GhidraBundleException if there's a problem activating
|
||||||
*/
|
*/
|
||||||
public void deactivateSynchronously(Bundle bundle)
|
public void deactivateSynchronously(Bundle bundle) throws GhidraBundleException {
|
||||||
throws InterruptedException, GhidraBundleException {
|
|
||||||
if (bundle.getState() == Bundle.UNINSTALLED) {
|
if (bundle.getState() == Bundle.UNINSTALLED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -593,7 +574,10 @@ public class BundleHost {
|
||||||
Bundle dependentBundle = dependentBundles.pop();
|
Bundle dependentBundle = dependentBundles.pop();
|
||||||
try {
|
try {
|
||||||
dependentBundle.uninstall();
|
dependentBundle.uninstall();
|
||||||
frameworkWiring.refreshBundles(dependentBundles);
|
if (dependentBundle.getState() != Bundle.UNINSTALLED) {
|
||||||
|
System.err.printf("It ain't uninstalled!\n");
|
||||||
|
}
|
||||||
|
refreshBundlesSynchronously(new ArrayList<>(dependentBundles));
|
||||||
}
|
}
|
||||||
catch (BundleException e) {
|
catch (BundleException e) {
|
||||||
GhidraBundleException exception =
|
GhidraBundleException exception =
|
||||||
|
@ -601,12 +585,11 @@ public class BundleHost {
|
||||||
fireBundleException(exception);
|
fireBundleException(exception);
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
waitFor(dependentBundle, Bundle.UNINSTALLED);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate a bundle, returning only after the bundle is inactive.
|
* Deactivate a bundle. Either an exception is thrown or the bundle will be in "UNINSTALLED" state.
|
||||||
*
|
*
|
||||||
* @param bundleLocation the bundle location identifier
|
* @param bundleLocation the bundle location identifier
|
||||||
* @throws InterruptedException if the wait is interrupted
|
* @throws InterruptedException if the wait is interrupted
|
||||||
|
@ -620,6 +603,39 @@ public class BundleHost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the specified bundles. This forces the update (replacement)
|
||||||
|
* or removal of packages exported by the specified bundles.
|
||||||
|
*
|
||||||
|
* @param bundles the bundles to refresh
|
||||||
|
* @see FrameworkWiring#refreshBundles
|
||||||
|
*/
|
||||||
|
protected void refreshBundlesSynchronously(Collection<Bundle> bundles) {
|
||||||
|
FrameworkWiring frameworkWiring = felixFramework.adapt(FrameworkWiring.class);
|
||||||
|
Semaphore sema = new Semaphore(0);
|
||||||
|
frameworkWiring.refreshBundles(bundles, new FrameworkListener() {
|
||||||
|
@Override
|
||||||
|
public void frameworkEvent(FrameworkEvent event) {
|
||||||
|
switch (event.getType()) {
|
||||||
|
case FrameworkEvent.ERROR:
|
||||||
|
Bundle bundle = event.getBundle();
|
||||||
|
Msg.error(BundleHost.this,
|
||||||
|
String.format("OSGi error refreshing bundle: %s", bundle));
|
||||||
|
break;
|
||||||
|
case FrameworkEvent.PACKAGES_REFRESHED:
|
||||||
|
sema.release();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
sema.acquire();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a listener for OSGi framework events.
|
* Remove a listener for OSGi framework events.
|
||||||
*
|
*
|
||||||
|
|
|
@ -523,7 +523,7 @@ public class GhidraSourceBundle extends GhidraBundle {
|
||||||
}
|
}
|
||||||
return anythingChanged | wipeBinDir();
|
return anythingChanged | wipeBinDir();
|
||||||
}
|
}
|
||||||
catch (IOException | GhidraBundleException | InterruptedException e) {
|
catch (IOException | GhidraBundleException e) {
|
||||||
Msg.showError(this, null, "source bundle clean error",
|
Msg.showError(this, null, "source bundle clean error",
|
||||||
"while attempting to delete the compiled directory, an exception was thrown", e);
|
"while attempting to delete the compiled directory, an exception was thrown", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ public class JavaScriptProvider extends GhidraScriptProvider {
|
||||||
bundleHost.deactivateSynchronously(osgiBundle);
|
bundleHost.deactivateSynchronously(osgiBundle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (GhidraBundleException | InterruptedException e) {
|
catch (GhidraBundleException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Msg.error(this, "while deactivating bundle for delete", e);
|
Msg.error(this, "while deactivating bundle for delete", e);
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue