Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 170722 - Issues with concurrent access to the authorization database
Summary: Issues with concurrent access to the authorization database
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Runtime (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 critical (vote)
Target Milestone: 3.3 M5   Edit
Assignee: John Arthorne CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 92887 170346 (view as bug list)
Depends on:
Blocks:
 
Reported: 2007-01-16 22:25 EST by Eugene Kuleshov CLA
Modified: 2007-04-19 08:17 EDT (History)
7 users (show)

See Also:


Attachments
Fix (3.09 KB, patch)
2007-02-02 13:31 EST, John Arthorne CLA
no flags Details | Diff
concurrent test case (2.00 KB, text/plain)
2007-02-02 14:19 EST, Eugene Kuleshov CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Eugene Kuleshov CLA 2007-01-16 22:25:42 EST
I am getting errors like this quite often. It seems like platform auth info is used by multiple plugins (Team/CVS, Subclipse, Mylar, etc) and there could be some concurrency issues. I noticed that none of the methods Platform.*AuthorizationInfo() are synchronized, so it is possible that .keyring file can be written from multiple threads at the same time.

Here is one of the stack traces:

Unable to read authorization database: C:\eclipse\eclipse-3.3M4\configuration\org.eclipse.core.runtime\.keyring.

java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2279)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2748)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)
at org.eclipse.core.internal.runtime.auth.AuthorizationDatabase.load(AuthorizationDatabase.java:292)
at org.eclipse.core.internal.runtime.auth.AuthorizationDatabase.load(AuthorizationDatabase.java:275)
at org.eclipse.core.internal.runtime.auth.AuthorizationDatabase.<init>(AuthorizationDatabase.java:95)
at org.eclipse.core.internal.runtime.auth.AuthorizationHandler.loadKeyring(AuthorizationHandler.java:58)
at org.eclipse.core.internal.runtime.auth.AuthorizationHandler.getAuthorizationInfo(AuthorizationHandler.java:176)
at org.eclipse.core.runtime.Platform.getAuthorizationInfo(Platform.java:608)
at org.eclipse.mylar.tasks.core.TaskRepository.getAuthInfo(TaskRepository.java:255)
at org.eclipse.mylar.tasks.core.TaskRepository.getAuthInfo(TaskRepository.java:274)
at org.eclipse.mylar.tasks.core.TaskRepository.getUserNameFromKeyRing(TaskRepository.java:158)
at org.eclipse.mylar.tasks.core.TaskRepository.getUserName(TaskRepository.java:152)
at org.eclipse.mylar.tasks.ui.TaskListManager.isCompletedToday(TaskListManager.java:705)
at org.eclipse.mylar.internal.context.ui.TaskListInterestFilter.isUninteresting(TaskListInterestFilter.java:58)
at org.eclipse.mylar.internal.context.ui.TaskListInterestFilter.select(TaskListInterestFilter.java:41)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListContentProvider.filter(TaskListContentProvider.java:250)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListContentProvider.getFilteredChildrenFor(TaskListContentProvider.java:217)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListContentProvider.getChildren(TaskListContentProvider.java:71)
at org.eclipse.jface.viewers.AbstractTreeViewer.getRawChildren(AbstractTreeViewer.java:1215)
at org.eclipse.jface.viewers.TreeViewer.getRawChildren(TreeViewer.java:490)
at org.eclipse.jface.viewers.AbstractTreeViewer.getFilteredChildren(AbstractTreeViewer.java:613)
at org.eclipse.jface.viewers.AbstractTreeViewer.getSortedChildren(AbstractTreeViewer.java:579)
at org.eclipse.jface.viewers.AbstractTreeViewer.updateChildren(AbstractTreeViewer.java:2420)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefreshStruct(AbstractTreeViewer.java:1720)
at org.eclipse.jface.viewers.TreeViewer.internalRefreshStruct(TreeViewer.java:688)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1695)
at org.eclipse.jface.viewers.AbstractTreeViewer.internalRefresh(AbstractTreeViewer.java:1651)
at org.eclipse.jface.viewers.StructuredViewer$8.run(StructuredViewer.java:1424)
at org.eclipse.jface.viewers.StructuredViewer.preservingSelection(StructuredViewer.java:1332)
at org.eclipse.jface.viewers.StructuredViewer.refresh(StructuredViewer.java:1422)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListView.refresh(TaskListView.java:1433)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListView.refresh(TaskListView.java:1421)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListView.refresh(TaskListView.java:1414)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListView.access$2(TaskListView.java:1385)
at org.eclipse.mylar.internal.tasks.ui.views.TaskListView$2$1.run(TaskListView.java:303)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:123)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3442)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3082)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:1945)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1909)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:425)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplication.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.internal.app.EclipseAppContainer.callMethod(EclipseAppContainer.java:522)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:147)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:104)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:74)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:354)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:170)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.core.launcher.Main.invokeFramework(Main.java:339)
at org.eclipse.core.launcher.Main.basicRun(Main.java:283)
at org.eclipse.core.launcher.Main.run(Main.java:984)
at org.eclipse.core.launcher.Main.main(Main.java:959)
Comment 1 Eugene Kuleshov CLA 2007-01-23 00:37:24 EST
Please note that shown stack trace is just one of the consequences and probably the most severe one. Another quite annoying one is when credentials for some particular host are being lost.
Comment 2 Benjamin Pasero CLA 2007-02-01 17:20:28 EST
See also Bug 170346
Comment 3 Ismael Juma CLA 2007-02-01 17:31:42 EST
Seems similar to bug #170346.
Comment 4 Ismael Juma CLA 2007-02-01 17:32:37 EST
I had not seen comment #2, sorry for the noise.
Comment 5 Mik Kersten CLA 2007-02-01 17:39:05 EST
I have also experienced this credentials loss.
Comment 6 Eugene Kuleshov CLA 2007-02-01 21:05:33 EST
Can owner of the org.eclipse.core.runtime.compatibility.auth module or someone from Platform Runtime please comment on this?

I believe this is quite bad issue and should be addressed as soon as possible. 

Corrupted .keyring file can lead to all kind of really nasty issues. Few times I saw that broken .keyring file was causing OutOfMemoryException on Eclipse startup, so it won't even start and I had to delete broken .keyring file. But for inexperienced user that would mean loss of the whole Eclipse workspace or even Eclipse reinstall.
Comment 7 John Arthorne CLA 2007-02-02 13:29:51 EST
I'll take this.
Comment 8 John Arthorne CLA 2007-02-02 13:31:43 EST
Created attachment 58129 [details]
Fix

This patch synchronizes access to the keyring. It also fixes a bug that was causing the keyring to be read too often. If you set authorization info, and then immediately read it back, there is no need to re-read the data from disk. The bug was that the cache timestamp was not updated on save (only on read).
Comment 9 John Arthorne CLA 2007-02-02 13:32:26 EST
Fix released.
Comment 10 Eugene Kuleshov CLA 2007-02-02 13:37:46 EST
(In reply to comment #8)
> Created an attachment (id=58129) [details]
> Fix

Great stuff!

> This patch synchronizes access to the keyring. 

By the way, do you like a junit test for that?

> It also fixes a bug that was
> causing the keyring to be read too often. If you set authorization info, and
> then immediately read it back, there is no need to re-read the data from disk.
> The bug was that the cache timestamp was not updated on save (only on read).

John, while you are on it, may I also suggest to add a latency for checking timestamp on the file system? I.e. don't check it more often then every second. I don't want to finger anyone, but some plugins could abuse getAuthInfo() call, which is currently checks the file timestamp on every call.
Comment 11 John Arthorne CLA 2007-02-02 13:54:19 EST
I'm assuming the target milestone was cleared accidentally.  A JUnit test would certainly be welcome. I think the current optimization is appropriate for most users - if there are clients accessing this kind of data very frequently, might I suggest they hold it in memory rather than going to the keyring every time.  If someone was, for example, using auth data when filtering items in a UI view, they could easily hang onto the data they need themselves.  Note also that for thread safety getAuthorizationInfo clones the returned auth HashMap, so it won't be a fast operation in any case.
Comment 12 Eugene Kuleshov CLA 2007-02-02 14:19:11 EST
Created attachment 58141 [details]
concurrent test case

Here is the concurrent test case that can be lauched as junit plugin test. It fail miserably with all kinds of exceptions (NPE, OOME, AIOBE, you name it) on Eclipse 3.3M4.
Comment 13 Eugene Kuleshov CLA 2007-02-02 14:21:35 EST
 (In reply to comment #11)
> I think the current optimization is appropriate for most
> users - if there are clients accessing this kind of data very frequently, might
> I suggest they hold it in memory rather than going to the keyring every time.

Right. That is what we had to do for Mylar. Thanks.
Perhaps it might be somehow reflected in the javadocs for the Platform.getAuthInfo() method...
Comment 14 Mik Kersten CLA 2007-02-02 16:18:40 EST
Excellent that this is fixed for M5!

Eugene: assuming that it won't have any bad behavior, let's leave the Mylar work-around for now, because mylar.tasks is not yet forked for 3.3.
Comment 15 John Arthorne CLA 2007-02-12 10:34:21 EST
*** Bug 170346 has been marked as a duplicate of this bug. ***
Comment 16 Michael Valenta CLA 2007-04-19 08:17:49 EDT
*** Bug 92887 has been marked as a duplicate of this bug. ***