Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 317713

Summary: Deadlock in SVNKitConnector when ProgressMonitor implementation queries display thread.
Product: [Technology] Subversive Reporter: Micha Riser <eclipse>
Component: CoreAssignee: Igor Burilo <igor.burilo>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
patch as promised in description i.vinnykov: iplog+

Description Micha Riser CLA 2010-06-23 11:18:02 EDT
Build Identifier: 20100218-1602

The SVNKitConnector has a thread which monitors all progress monitors for cancellation. While querying the IProgressMonitor.isCanceled() it superflously holds the lock on its list of monitors. Therefore, when the progress monitor needs a lock (such as the display thread) inside its isCanceled() implementation there is potential for deadlocks when the thread holding that resource is simultaneously trying to remove a monitor from the locked list.

The SVNKitConnector thread does not need to hold the lock. It can copy the list of monitors and release the lock before iterating the list. I provide a patch which does exactly this.

By the way, I could not find the repository of org.polarion.team.svn.connector.svnkit.SVNConnector.java Is it not publically availiable for reading?

Below is a stack trace which shows the deadlock scenario.

Thread [SVN-QLAF4] (Suspended)	
	SVNKitConnector$ProgressMonitorThread.remove(SVNKitConnector$ProgressMonitorWrapper) line: 1578	
	SVNKitConnector$ProgressMonitorWrapper.interrupt() line: 1652	
	SVNKitConnector.checkout(SVNEntryRevisionReference, String, int, long, ISVNProgressMonitor) line: 204	
	ThreadNameModifier.checkout(SVNEntryRevisionReference, String, int, long, ISVNProgressMonitor) line: 78	
	CheckoutAsOperation.doCheckout(IProgressMonitor, IPath) line: 169	
	CheckoutAsOperation$1.run(IProgressMonitor) line: 127	
	ProgressMonitorUtility.doSubTask(IActionOperation, IUnprotectedOperation, IProgressMonitor, int, int) line: 118	
	CheckoutAsOperation.runImpl(IProgressMonitor) line: 125	
	CheckoutAsOperation(AbstractActionOperation).run(IProgressMonitor) line: 81	
	ProgressMonitorUtility.doTask(IActionOperation, IProgressMonitor, int, int) line: 104	
	CompositeOperation.runImpl(IProgressMonitor) line: 95	
	CompositeOperation(AbstractActionOperation).run(IProgressMonitor) line: 81	
	UILoggedOperation(LoggedOperation).run(IProgressMonitor) line: 39	
	ProgressMonitorUtility.doTask(IActionOperation, IProgressMonitor, int, int) line: 104	
	ProgressMonitorUtility.doTaskExternal(IActionOperation, IProgressMonitor, ILoggedOperationFactory) line: 90	
	ProgressMonitorUtility.doTaskExternal(IActionOperation, IProgressMonitor) line: 81	
	SVNTeamProjectSetCapability.addToWorkspace(String[], ProjectSetSerializationContext, IProgressMonitor) line: 98	
	ProjectSetImporter.importProjectSet(TypeSafeUIProjectSetSerializationContext, XMLMemento, IProgressMonitor) line: 73	
	ProjectSetImporter.importProjectSet(String, InputStream, Shell, IProgressMonitor) line: 31	
	Installer$1.resultRun() line: 36	
	Installer$1.resultRun() line: 1	
	Installer$1(ResultRunnable<T>).run() line: 31	
	UISynchronizer(Synchronizer).syncExec(Runnable) line: 179	
	UISynchronizer.syncExec(Runnable) line: 150	
	Display.syncExec(Runnable) line: 4113	
	Installer.installTeamSet(IGenericApplicationInfo, IProgressMonitor) line: 45	
	Installer.install(IGenericApplicationInfo, IProgressMonitor) line: 23	
	ImportGenericAppWizard.runFinish(IProgressMonitor) line: 129	
	GeneratedWizard$1.run(IProgressMonitor) line: 71	
	ModalContext.runInCurrentThread(IRunnableWithProgress, IProgressMonitor) line: 464	
	ModalContext.run(IRunnableWithProgress, boolean, IProgressMonitor, Display) line: 372	
	WizardDialog.run(boolean, boolean, IRunnableWithProgress) line: 944	
	GeneratedWizard.performOperation(IWizardContainer, IRunnableWithProgress, boolean) line: 95	
	ImportGenericAppWizard(GeneratedWizard).runFinish() line: 78	
	ImportGenericAppWizard.performFinish() line: 106	
	WizardDialog.finishPressed() line: 752	
	WizardDialog.buttonPressed(int) line: 373	
	Dialog$2.widgetSelected(SelectionEvent) line: 624	
	TypedListener.handleEvent(Event) line: 228	
	EventTable.sendEvent(Event) line: 84	
	Button(Widget).sendEvent(Event) line: 1176	
	Display.runDeferredEvents() line: 3493	
	Display.readAndDispatch() line: 3112	
	WizardDialog(Window).runEventLoop(Shell) line: 825	
	WizardDialog(Window).open() line: 801	
	WizardHandler$Import.executeHandler(ExecutionEvent) line: 146	
	WizardHandler$Import(WizardHandler).execute(ExecutionEvent) line: 273	
	HandlerProxy.execute(ExecutionEvent) line: 294	
	Command.executeWithChecks(ExecutionEvent) line: 476	
	ParameterizedCommand.executeWithChecks(Object, Object) line: 508	
	HandlerService.executeCommand(ParameterizedCommand, Event) line: 169	
	SlaveHandlerService.executeCommand(ParameterizedCommand, Event) line: 241	
	ActionFactory$WorkbenchCommandAction(CommandAction).runWithEvent(Event) line: 157	
	ActionFactory$WorkbenchCommandAction(CommandAction).run() line: 171	
	ImportResourcesAction.run() line: 97	
	ImportResourcesAction(BaseSelectionListenerAction).runWithEvent(Event) line: 168	
	ActionContributionItem.handleWidgetSelection(Event, boolean) line: 584	
	ActionContributionItem.access$2(ActionContributionItem, Event, boolean) line: 501	
	ActionContributionItem$5.handleEvent(Event) line: 411	
	EventTable.sendEvent(Event) line: 84	
	MenuItem(Widget).sendEvent(Event) line: 1176	
	Display.runDeferredEvents() line: 3493	
	Display.readAndDispatch() line: 3112	
	Workbench.runEventLoop(Window$IExceptionHandler, Display) line: 2405	
	Workbench.runUI() line: 2369	
	Workbench.access$4(Workbench) line: 2221	
	Workbench$5.run() line: 500	
	Realm.runWithDefault(Realm, Runnable) line: 332	
	Workbench.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 493	
	PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor) line: 149	
	IDEApplication.start(IApplicationContext) line: 113	
	EclipseAppHandle.run(Object) line: 194	
	EclipseAppLauncher.runApplication(Object) line: 110	
	EclipseAppLauncher.start(Object) line: 79	
	EclipseStarter.run(Object) line: 368	
	EclipseStarter.run(String[], Runnable) line: 179	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
	Method.invoke(Object, Object...) line: 597	
	Main.invokeFramework(String[], URL[]) line: 559	
	Main.basicRun(String[]) line: 514	
	Main.run(String[]) line: 1311	
	Main.main(String[]) line: 1287	

Thread [SVN Kit 1.2 Connector] (Suspended)	
	Object.wait(long) line: not available [native method] [local variables unavailable]	
	RunnableLock(Object).wait() line: 485	
	UISynchronizer(Synchronizer).syncExec(Runnable) line: 186	
	UISynchronizer.syncExec(Runnable) line: 150	
	Display.syncExec(Runnable) line: 4113	
	UIProgressMonitor.displayExec(ResultRunnable<T>, T) line: 21	
	UIProgressMonitor.isCanceled() line: 72	
	SubProgressMonitorWithInfo(ProgressMonitorWrapper).isCanceled() line: 106	
	SubProgressMonitorWithInfo(ProgressMonitorWrapper).isCanceled() line: 106	
	SubProgressMonitorWithInfo(ProgressMonitorWrapper).isCanceled() line: 106	
	SVNProgressMonitor.isActivityCancelled() line: 84	
	SVNKitConnector$ProgressMonitorThread.checkForActivityCancelled() line: 1604	
	SVNKitConnector$ProgressMonitorThread.run() line: 1585	


Reproducible: Sometimes

Steps to Reproduce:
See details
Comment 1 Micha Riser CLA 2010-06-23 11:19:05 EDT
Created attachment 172514 [details]
patch as promised in description
Comment 2 Alexander Gurov CLA 2011-03-26 05:58:15 EDT
Thank you very much for your efforts and I'm sorry it took so long to just check the issue report.
I fixed the issue for all of the existing connectors.