diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/resources/ResourcesPlugin.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/resources/ResourcesPlugin.java index efc710e73d2..76ce99b9724 100644 --- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/resources/ResourcesPlugin.java +++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/resources/ResourcesPlugin.java @@ -568,7 +568,8 @@ public void start(BundleContext context) throws Exception { private final class WorkspaceInitCustomizer implements ServiceTrackerCustomizer { private final BundleContext context; private volatile Workspace workspace; - private ServiceRegistration workspaceRegistration; + private volatile ServiceRegistration workspaceRegistration; + private volatile Job workspaceRegistrationJob; private WorkspaceInitCustomizer(BundleContext context) { this.context = context; @@ -592,7 +593,27 @@ public Workspace addingService(ServiceReference reference) { if (!result.isOK()) { getLog().log(result); } - workspaceRegistration = context.registerService(IWorkspace.class, workspace, null); + // Publish IWorkspace asynchronously: registerService dispatches + // ServiceEvent.REGISTERED synchronously to every + // ServiceTracker listener, and several of them + // (e.g. save-participant registrations) do non-trivial work + // that would otherwise block the startup critical path. + // Static callers using ResourcesPlugin.getWorkspace() are + // unaffected since it reads the field directly. + Job job = Job.create("Register IWorkspace service", (IProgressMonitor monitor) -> { //$NON-NLS-1$ + Workspace ws = workspace; + if (ws != null) { + try { + workspaceRegistration = context.registerService(IWorkspace.class, ws, null); + } catch (IllegalStateException e) { + // bundle context became invalid during shutdown + } + } + return Status.OK_STATUS; + }); + job.setSystem(true); + workspaceRegistrationJob = job; + job.schedule(); return workspace; } catch (CoreException e) { getLog().log(e.getStatus()); @@ -611,10 +632,21 @@ public void modifiedService(ServiceReference reference, Workspace serv @Override public void removedService(ServiceReference reference, Workspace service) { if (service == workspace) { - try { - workspaceRegistration.unregister(); - } catch (RuntimeException e) { - getLog().log(Status.warning("Unregistering workspaces throws an exception", e)); //$NON-NLS-1$ + Job job = workspaceRegistrationJob; + if (job != null) { + try { + job.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + ServiceRegistration registration = workspaceRegistration; + if (registration != null) { + try { + registration.unregister(); + } catch (RuntimeException e) { + getLog().log(Status.warning("Unregistering workspaces throws an exception", e)); //$NON-NLS-1$ + } } try { service.close(null);