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.
Seems to be random - doesn't happen all the time. I produced this state starting NetBeans normally on a 2 processor machine, WinXP. Note in the attached stack trace, there are three threads all doing something with an EditorDocument. The EQ and java parsing thread are waiting to lock on the editor document.
Created attachment 12524 [details] Thread dump
After consultation reassigning Petr.
After consultation reassigning to Petr.
The DefaultRP is in document's writeAccess and tries to lock PositionRef.Manager The Java source parsing thread has the PositionRef.Manager already locked and wants read access to the editor. The question is what is the correct order. I've tried to lock PR.M before writeEnter to document and it seems it works, but I'm not sure about the order used in other parts of code (I think the opposite order should be used: Doc first, PR.M second). I'll attach the diff. Mila, can you please review it?
Created attachment 12982 [details] Possible lock order fix (PR.M first)
Unfortunately I think we are facing one more problem here. If you look at the thread dump of the Java parsing thread it is already inside a document renderer so it should normally be no-op to acquire another lock on the same doc. Unfortunately there is likely a _different_ document that was just loaded (by the second RP thread) so in fact the locks acquired are like this: Java parsing thread: 1. orig-doc-read-lock 2. PR.M and wants new-doc-read-lock RP: 1. new-doc-write-lock 2. CES.getLock() and wants PR.M so it looks like counter-locking of PR.M with new-doc. As an relatively low-cost experiment we could try to merge PR.M and CES.getLock() into a single lock. I do not try to bet whether it would bring another deadlocks or not. I think that it could help in our case as just one thread at time could proceed through CES.getLock() and the new-doc would not be known to other threads until CES.getLock() gets released which should avoid the deadlock. Another possibility could be to write-lock the orig-doc (if there was any) before loading the new-doc. Not sure how feasible is that.
So it seems we finally know what's going on. There is no reload in progress, no oldDoc and newDoc and the java parser holds no orig-doc-read-lock while parsing. It may seem stragne but it is OK, as there is no document yet loaded and the java parser is pulling directly from stream. What happened: Java parser was already parsing a stream (no Document anywhere), when an open request came. The parser thread was about to create a new PositionRef, found no document, so locked the PR.M and tried to proceed w/o document. But the document openning thread have just loaded the document and (as a writer) notified the PR.M. PR.M saves the document reference and tries to convert all registered PositionRefs to this new state. To do this, it have to wait to lock the PR.M The parser thread gets another timeslice and continues with creating the PositionRef, but this time the document is already present (something the PR.M was not prepared for) and deadlocks trying to read-lock it. Mila's proposed solution could fix the problem so I'll try to implement it.
Yes, my appologies - I've seen the PositionRef$Manager$DocumentRenderer.renderrender() in the stacktrace of java parsing thread and did not realize that it finally went through the branch for the case when the actual document is null i.e. through the direct invocation of run() in the renderer.
Fixed using the proposed solution (locking on CES's lock instead of PR.M private lock). openide/src/org/openide/text/PositionRef.java ,v1.51
verified - Tim, reopen if you reproduce it again