Bug 253794 p2 parser error - XML document structures must start and end within the same entity
diff --git a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/core/ProvisioningEventBus.java b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/core/ProvisioningEventBus.java
index 08ff80e..6f7becf 100644
--- a/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/core/ProvisioningEventBus.java
+++ b/bundles/org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/core/ProvisioningEventBus.java
@@ -22,6 +22,12 @@
 	private EventListeners asyncListeners = new EventListeners();
 	private EventManager eventManager = new EventManager("Provisioning Event Dispatcher"); //$NON-NLS-1$
 
+	private Object dispatchEventLock = new Object();
+	/* @GuardedBy("dispatchEventLock") */
+	private boolean closed = false;
+	/* @GuardedBy("dispatchEventLock") */
+	private int dispatchingEvents = 0;
+
 	/* (non-Javadoc)
 	 * @see org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus#addListener(org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener)
 	 */
@@ -60,6 +66,10 @@
 	 * @see org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus#publishEvent(java.util.EventObject)
 	 */
 	public void publishEvent(EventObject event) {
+		synchronized (dispatchEventLock) {
+			if (closed)
+				return;
+		}
 		/* queue to hold set of listeners */
 		ListenerQueue listeners = new ListenerQueue(eventManager);
 
@@ -74,7 +84,10 @@
 		listeners = new ListenerQueue(eventManager);
 		synchronized (asyncListeners) {
 			listeners.queueListeners(asyncListeners, this);
-			listeners.dispatchEventAsynchronous(0, event);
+			synchronized (dispatchEventLock) {
+				if (!closed)
+					listeners.dispatchEventAsynchronous(0, event);
+			}
 		}
 	}
 
@@ -82,11 +95,22 @@
 	 * @see org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus#dispatchEvent(java.lang.Object, java.lang.Object, int, java.lang.Object)
 	 */
 	public void dispatchEvent(Object eventListener, Object listenerObject, int eventAction, Object eventObject) {
+		synchronized (dispatchEventLock) {
+			if (closed)
+				return;
+			dispatchingEvents++;
+		}
 		try {
 			((ProvisioningListener) eventListener).notify((EventObject) eventObject);
 		} catch (Exception e) {
 			e.printStackTrace();
 			//TODO Need to do the appropriate logging
+		} finally {
+			synchronized (dispatchEventLock) {
+				dispatchingEvents--;
+				if (dispatchingEvents == 0)
+					dispatchEventLock.notifyAll();
+			}
 		}
 	}
 
@@ -94,6 +118,21 @@
 	 * @see org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus#close()
 	 */
 	public void close() {
-		eventManager.close();
+		boolean interrupted = false;
+		synchronized (dispatchEventLock) {
+			eventManager.close();
+			closed = true;
+			while (dispatchingEvents != 0) {
+				try {
+					dispatchEventLock.wait(30000); // we're going to cap waiting time at 30s
+					break;
+				} catch (InterruptedException e) {
+					// keep waiting but flag interrupted
+					interrupted = true;
+				}
+			}
+		}
+		if (interrupted)
+			Thread.currentThread().interrupt();
 	}
 }