This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 40766 - Deadlock when PositionRef is started to be added prior to document opening
Summary: Deadlock when PositionRef is started to be added prior to document opening
Status: VERIFIED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: Text (show other bugs)
Version: 3.x
Hardware: All All
: P2 blocker (vote)
Assignee: Petr Nejedly
URL:
Keywords: THREAD
: 40856 40865 (view as bug list)
Depends on: 40951
Blocks:
  Show dependency tree
 
Reported: 2004-03-04 16:05 UTC by Miloslav Metelka
Modified: 2008-12-22 21:38 UTC (History)
4 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Apologies, same threads as text attachment (6.37 KB, text/plain)
2004-03-04 16:09 UTC, Miloslav Metelka
Details
Proposed patch for release36 branch (2.94 KB, patch)
2004-03-11 12:27 UTC, Petr Nejedly
Details | Diff
Test failing test (2.42 KB, patch)
2004-03-12 10:55 UTC, Jaroslav Tulach
Details | Diff
Fix to make both tests succeed (11.19 KB, patch)
2004-03-12 14:45 UTC, Jaroslav Tulach
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Miloslav Metelka 2004-03-04 16:05:22 UTC
There is a deadlock between the following threads:

[ideexec] "Java source parsing" daemon prio=1
tid=0x0051ab60 nid=0x47 in Object.wait()
[e9e80000..e9e819a0]
  [ideexec] 	at java.lang.Object.wait(Native Method)
  [ideexec] 	- waiting on <0xf1519d50> (a
org.netbeans.modules.editor.NbEditorDocument)
  [ideexec] 	at java.lang.Object.wait(Object.java:429)
  [ideexec] 	at
javax.swing.text.AbstractDocument.readLock(AbstractDocument.java:1385)
  [ideexec] 	- locked <0xf1519d50> (a
org.netbeans.modules.editor.NbEditorDocument)
  [ideexec] 	at
org.netbeans.editor.BaseDocument.render(BaseDocument.java:881)
  [ideexec] 	at
org.openide.text.PositionRef$Manager$DocumentRenderer.render(PositionRef.java:867)
  [ideexec] 	at
org.openide.text.PositionRef$Manager$DocumentRenderer.renderToObject(PositionRef.java:884)
  [ideexec] 	at
org.openide.text.PositionRef$Manager$Kind.toMemory(PositionRef.java:450)
  [ideexec] 	at
org.openide.text.PositionRef$Manager$DocumentRenderer.run(PositionRef.java:1022)
  [ideexec] 	- locked <0xf1502af0> (a
org.openide.windows.CloneableOpenSupport$Listener)
  [ideexec] 	at
org.openide.text.PositionRef$Manager$DocumentRenderer.render(PositionRef.java:869)
  [ideexec] 	at
org.openide.text.PositionRef$Manager$DocumentRenderer.renderToObject(PositionRef.java:884)
  [ideexec] 	at
org.openide.text.PositionRef$Manager.addPosition(PositionRef.java:367)
  [ideexec] 	at
org.openide.text.PositionRef.init(PositionRef.java:81)
  [ideexec] 	at
org.openide.text.PositionRef.<init>(PositionRef.java:76)
  [ideexec] 	at
org.openide.text.PositionRef.<init>(PositionRef.java:53)
  [ideexec] 	at
org.openide.text.CloneableEditorSupport.createPositionRef(CloneableEditorSupport.java:938)
  [ideexec] 	at
org.netbeans.modules.java.parser.DocumentModelBuilder.createStableBounds(DocumentModelBuilder.java:168)
  [ideexec] 	at
org.netbeans.modules.java.parser.DocumentModelBuilder.createPackage(DocumentModelBuilder.java:49)
  [ideexec] 	at
org.netbeans.modules.java.gj.V8TreeTranslator._case(V8TreeTranslator.java:181)
  [ideexec] 	at
org.netbeans.lib.javac.v8.tree.Tree$TopLevel.visit(Tree.java:344)
  [ideexec] 	at
org.netbeans.modules.java.gj.V8TreeTranslator.process(V8TreeTranslator.java:94)
  [ideexec] 	at
org.netbeans.modules.java.gj.ParserEngine.completeRequest(ParserEngine.java:359)
  [ideexec] 	at
org.netbeans.modules.java.gj.ParserEngine.parseObject(ParserEngine.java:175)
  [ideexec] 	- locked <0xf1502d18> (a
org.netbeans.modules.java.gj.ParserEngine)
  [ideexec] 	at
org.netbeans.modules.java.gj.JavaParserEngine.process(JavaParserEngine.java:72)
  [ideexec] 	- locked <0xf658c438> (a java.lang.Class)
  [ideexec] 	at
org.netbeans.modules.java.parser.ParsingSupport$Processor.process(ParsingSupport.java:711)
  [ideexec] 	at
org.netbeans.modules.java.parser.ParsingSupport$Processor.parseLockModel(ParsingSupport.java:662)
  [ideexec] 	at
org.netbeans.modules.java.parser.ParsingSupport$Processor.run(ParsingSupport.java:593)
  [ideexec] 	at
org.openide.util.Task.run(Task.java:136)
  [ideexec] 	at
org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:330)
  [ideexec] 	at
org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:686)

and

[ideexec] "Module-Actions" daemon prio=1
tid=0x0120fe80 nid=0xa9 waiting for monitor entry
[e9980000..e99819a0]
  [ideexec] 	at
org.openide.text.CloneableEditorSupport.openDocument(CloneableEditorSupport.java:509)
  [ideexec] 	- waiting to lock <0xf1502af0> (a
org.openide.windows.CloneableOpenSupport$Listener)
  [ideexec] 	at
org.openide.text.PositionBounds.setText(PositionBounds.java:70)
  [ideexec] 	at
org.netbeans.modules.java.codegen.CodeGenerator.fillTextBounds(CodeGenerator.java:106)
  [ideexec] 	at
org.netbeans.modules.java.codegen.ElementBinding$PartialGenerator.run(ElementBinding.java:480)
  [ideexec] 	at
org.netbeans.modules.java.codegen.SourceText$1.run(SourceText.java:239)
  [ideexec] 	at
org.netbeans.editor.BaseDocument.runAtomicAsUser(BaseDocument.java:908)
  [ideexec] 	at
org.netbeans.editor.GuardedDocument.runAtomic(GuardedDocument.java:217)
  [ideexec] 	at
org.openide.text.NbDocument.runAtomic(NbDocument.java:340)
  [ideexec] 	at
org.netbeans.modules.java.codegen.SourceText.runAtomic(SourceText.java:258)
  [ideexec] 	at
org.netbeans.modules.java.codegen.ElementBinding.regenerateHeader(ElementBinding.java:346)
  [ideexec] 	at
org.netbeans.modules.java.codegen.Clazz.changeSuperclass(Clazz.java:91)
  [ideexec] 	at
org.netbeans.modules.java.model.ClassElementImpl.setSuperclass(ClassElementImpl.java:241)
  [ideexec] 	at
org.openide.src.ClassElement.setSuperclass(ClassElement.java:286)
  [ideexec] 	at
org.netbeans.modules.junit.TestCreator.fillGeneral(TestCreator.java:363)
  [ideexec] 	at
org.netbeans.modules.junit.TestCreator.fillSuiteClass(TestCreator.java:444)
  [ideexec] 	at
org.netbeans.modules.junit.TestCreator.createTestSuite(TestCreator.java:95)
  [ideexec] 	at
org.netbeans.modules.junit.CreateTestAction.createSuiteTest(CreateTestAction.java:214)
  [ideexec] 	at
org.netbeans.modules.junit.CreateTestAction.createTest(CreateTestAction.java:266)
  [ideexec] 	at
org.netbeans.modules.junit.CreateTestAction.performAction(CreateTestAction.java:152)
  [ideexec] 	at
org.openide.util.actions.NodeAction.performAction(NodeAction.java:193)
  [ideexec] 	at
org.openide.util.actions.CallableSystemAction$1.run(CallableSystemAction.java:78)
  [ideexec] 	at
org.openide.util.actions.CallableSystemAction$ActionRunnable.actionPerformed(CallableSystemAction.java:247)
  [ideexec] 	at
org.netbeans.core.ModuleActions.invokeAction(ModuleActions.java:71)
  [ideexec] 	at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
  [ideexec] 	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  [ideexec] 	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  [ideexec] 	at
java.lang.reflect.Method.invoke(Method.java:324)
  [ideexec] 	at
org.openide.util.actions.CallableSystemAction.invokeAction(CallableSystemAction.java:179)
  [ideexec] 	at
org.openide.util.actions.CallableSystemAction.access$000(CallableSystemAction.java:31)
  [ideexec] 	at
org.openide.util.actions.CallableSystemAction$ActionRunnable.doRun(CallableSystemAction.java:241)
  [ideexec] 	at
org.openide.util.actions.CallableSystemAction$2.run(CallableSystemAction.java:111)
  [ideexec] 	at
org.openide.util.Task.run(Task.java:136)
  [ideexec] 	at
org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:330)
  [ideexec] 	at
org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:686)
Comment 1 Miloslav Metelka 2004-03-04 16:09:36 UTC
Created attachment 13829 [details]
Apologies, same threads as text attachment
Comment 2 Miloslav Metelka 2004-03-04 16:26:00 UTC
The deadlock happens like this:
Thread 1)
  a) PositionRef$Manager.addPosition() gets called.
  b) PositionRef$Manager.doc is tried to be read-locked but it is null
so the locking is skipped
  c) monitor on CloneableOpenSupport$Listener is entered
  d) PositionRef$Manager$Kind.toMemory() gets called but this time the
PositionRef$Manager.doc is already assigned so it's attempted to be
read-locked by DocumentRenderer but it waits for the other thread that
does NbDocument.runAtomic() which already acquired write-lock on it.

Thread 2)
 a) NbDocument.runAtomic() write-locks the document.
 b) An attempt to openDocument() will cause the monitor on
CloneableOpenSupport$Listener to be entered which counter-locks with
the first thread.

Petre, not sure whether this is doable but IMHO we could try to avoid
the situation when the second nested doc-renderer sees the loaded
document. It should get null as well so that the counter-locking does
not occur.
Comment 3 Petr Nejedly 2004-03-04 17:00:45 UTC
We can give it null using ThreadLocal magic.
I'll look at it more, it may be possible to solve it better way.
Comment 4 Petr Nejedly 2004-03-05 10:04:12 UTC
Idea:
PR$Manager already wraps all accesses to document into
DocumentRenderer, regardless of current availability of Document.
What if we align all these document accesses with Mutex, so use the
Mutex (always serialized the same way as document) as a guard in case
of null document.
We can also use its writeRequest for actually setting the document
instance, thus prevent document from popping up in teh middle of
to/fromMemory conversion.
Comment 5 Petr Nejedly 2004-03-05 13:06:32 UTC
Seems it may work. I'm running it currently. Needs more testing.
Comment 6 Petr Nejedly 2004-03-08 12:07:12 UTC
My current solution acquires mutex readlock for all read-document
accesses from PositionRef.Manager and acquires mutex write lock for
all document setting calls.

This means that one can acquire a readlock on the document and then
call a method on PR.M, which then tries to acquire read lock on the
mutex -> different lock order. But these are read locks, which can be
acquired cuncurrently, os it should be no problem.

If I change the order (read-lock the mutex from inside the document's
read access with carefull rollback-retry for
null-document-before-real-document-now), lhe lock order will be OK,
but the code will be more compilcated.

Mila's idea of simulating null document during whole call looked
promising, but might cause bad incosistencies as some threads would
operate on the manager structures thinking there is no doc, while
other will see a doc.
Comment 7 Petr Nejedly 2004-03-08 16:56:56 UTC
My fix was integrated into trunk,
openide/src/org/openide/text/PositionRef.java,v1.52

Comment 8 Marian Mirilovic 2004-03-09 12:59:44 UTC
Petr, Mila, 
do you plan/want to fix this for NB3.6 ?

If so - ask for review, else - ask for waiver......
Comment 9 Petr Nejedly 2004-03-09 13:14:54 UTC
No. I've rolled back the change and have to reopen this, as my fix
caused another deadlock.
Comment 10 Petr Nejedly 2004-03-09 13:24:16 UTC
Another idea: Always keep (at least dummy) document in PR.M for the
purpose of locking.
Comment 11 Miloslav Metelka 2004-03-09 13:59:59 UTC
Just a raw idea: I'm wondering whether we could call getDocument()
prior to the actual creation of the PositionRef. If the document would
not be opened that would be no-op returning null. If it would just be
in the process of being loaded by RP thread then the particular thread
would become blocked until the loading finishes and the document
becomes known. Of course we need to prevent deadlocking of the RP
thread itself when attaching positionref but AFAIK there should
already be a threadlocal LOCAL_LOAD_TASK variable that should prevent
that. Not sure though whether I did not overlook anything important.
Comment 12 _ ttran 2004-03-09 14:07:27 UTC
*** Issue 40856 has been marked as a duplicate of this issue. ***
Comment 13 _ ttran 2004-03-09 16:59:48 UTC
*** Issue 40865 has been marked as a duplicate of this issue. ***
Comment 14 Petr Nejedly 2004-03-11 09:50:02 UTC
Fixed again, test added.

openide/src/org/openide/text/CloneableEditorSupport.java,v1.118
openide/src/org/openide/text/PositionRef.java,v1.54
openide/test/unit/src/org/openide/text/Deadlock40766Test.java,v1.1
Comment 15 Jiri Skrivanek 2004-03-11 10:03:50 UTC
It appeared in continuos build of NB36:

http://www.netbeans.org/download/release36/buildlogs/continuous/20040311-0730/xtest_results/testrun_040311-084050/logs/ide_qa-functional.log

It could be fixed fixed in NB36, if the fix will be successful in trunk.
Comment 16 Petr Nejedly 2004-03-11 12:27:38 UTC
Created attachment 13943 [details]
Proposed patch for release36 branch
Comment 17 Petr Nejedly 2004-03-11 12:31:58 UTC
I'd like to fix it in rel3.6.
Yardo, could you please review the patch for release36 branch
(the same as for dev, except it doesn't contain the test hooks and the
test is ommited from the branch)
Comment 18 Jaroslav Tulach 2004-03-11 13:44:45 UTC
We worked with Petr to create a test that would simulate the deadlock.
We succeeded and reproduced the problem. Then Petr created his fix and
the test started to pass. That is why it is easy to confirm that
Petr's solution fixes the problem. However I have to say that the
probability that another problem will be introduced is not zero.
Comment 19 Jaroslav Tulach 2004-03-12 10:54:27 UTC
I think I have simulated a deadlock caused by this fix. I will attach
the test. In my opinion the correct fix of both issues would use
"enter barrier" for everyone who wants to change state of document and
not whole sychronized block around the whole operations with document.
Comment 20 Jaroslav Tulach 2004-03-12 10:55:35 UTC
Created attachment 13958 [details]
Test failing test
Comment 21 Jaroslav Tulach 2004-03-12 14:45:05 UTC
Created attachment 13966 [details]
Fix to make both tests succeed
Comment 22 _ ttran 2004-03-12 14:54:08 UTC
remove 36_HR_FIX
Comment 23 Petr Nejedly 2004-03-15 16:16:10 UTC
Integrated Yarda's test, integrated new test for 38013 deadlock:
openide/test/unit/src/org/openide/text/Deadlock40766Test.java,v1.2

Fixed all 3 deadlocks using Yarda's enter barrier patch:
openide/src/org/openide/text/CloneableEditorSupport.java,v1.120
openide/src/org/openide/text/PositionRef.java,v1.55

Comment 24 Marian Mirilovic 2004-08-10 10:06:39 UTC
verified