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.
Summary: | IllegalStateException permanently appears in log | ||
---|---|---|---|
Product: | utilities | Reporter: | Jiri Skrivanek <jskrivanek> |
Component: | Search | Assignee: | Marian Petras <mpetras> |
Status: | VERIFIED FIXED | ||
Severity: | blocker | CC: | dmladek, jglick, jtulach, lhasik, mmirilovic, tboudreau |
Priority: | P2 | Keywords: | THREAD |
Version: | 3.x | ||
Hardware: | PC | ||
OS: | Windows ME/2000 | ||
Issue Type: | DEFECT | Exception Reporter: | |
Attachments: | Full stack trace |
Description
Jiri Skrivanek
2003-09-08 10:31:01 UTC
Created attachment 11541 [details]
Full stack trace
reassigned to openide/actions *** Issue 35955 has been marked as a duplicate of this issue. *** Exception comes from module org.netbeans.modules.search. That's why I am cc-ing issues@utilities.netbeans.org. Still happening in NBdev #200309170100 *** Issue 35973 has been marked as a duplicate of this issue. *** It is caused by calling findAction.setActionPerformer(...) in a request processor's thread in method org.netbeans.modules.search.FindActionManager.propertyChange(...) It was being called directly in the original source code and moved to a request processor later in order to avoid a deadlock. I do know the details of the deadlock so I will try to change it back (so the method is called in the default thread) and see if the change causes some deadlock or not. (The above change was made more than three years ago.) *** Issue 36178 has been marked as a duplicate of this issue. *** :-O Change was made 3 years ago and now, 2 weeks ago started throwing an E.? Incredible:-| That's not so incredible. The exception started being thrown simply because a test whether the method (mentioned in the initial bug description) is called in the AWT Event thread was added. The test was added to revision 1.87 of source code of class org.openide.awt.Actions. Why close issue #36178? I already have a patch for it and was planning to check it in shortly. If interested, try: if(TopComponent.Registry.PROP_CURRENT_NODES.equals(propName) || TopComponent.Registry.PROP_ACTIVATED.equals(propName)) { - // PREVENT deadlock - // do not depend on locking order of - // CookieSet[.add/remove()] and TopComponent[.attach()]. - RequestProcessor.getDefault().post(new Runnable() { - public void run() { - someoneActivated(); - } - }); + someoneActivated(); } } Sorry that I didn't check it in already - I was afraid of recreating whatever deadlock was being mentioned here. (Maybe it is obsolete.) I am running with this patch for a while now with no apparent problems. Jesse, it is clearly THE FIX. I've tried it, too, and found only a minor problem so far. The minor problem is that the exception is still thrown if you try to uninstall the Utilities module individually. It is because the module installer's method uninstalled() is apparently not called in the AWT event queue. OK, so change unhook slightly: public void unhook() { setHookListener(null); performer = null; Mutex.EVENT.readAccess(new Runnable() { public void run() { someoneActivated(); } }); findAction = null; } That should be all you need. someoneActivated() uses GUI methods (like the window system) and ought to be called from EQ. I just integrated the fix. Diff of method propertyChange(...): - // PREVENT deadlock - // do not depend on locking order of - // CookieSet[.add/remove()] and TopComponent[.attach()]. - RequestProcessor.getDefault().post(new Runnable() { - public void run() { - someoneActivated(); - } - }); + someoneActivated(); (i.e. exactly as Jesse suggested) Diff of method unhook(): - someoneActivated(); + + /* + * We just need to run method 'someoneActivated' + * in the AWT event dispatching thread. We use + * Mutex.EVENT for this task. + * + * We use Mutex.Action rather than Runnable. + * The reason is that Runnable could be run + * asynchronously which is undesirable during + * uninstallation (we do not want any instance/class + * from this module to be in use by the time + * ModuleInstall.uninstalled() returns). + */ + Mutex.EVENT.readAccess(new Mutex.Action() { + public Object run() { + someoneActivated(); + return null; + } + }); All right... careful with blocking on EQ from ModuleInstall, though. Not really safe. Of course it is also undesirable for module code to run after a module has nominally been uninstalled (as frequently happens in the current system). I am not sure what the best resolution for this conflict is currently; using Mutex.Action here for now ought to be OK. The best resolution would be to rewrite the code to new ActionMap system: instead of listening on each change of activated window, listen on creation of new ones. If a new TopComponent is created and it is of desired type, call topComponent.getActionMap().put ("org.openide.actions.FindAction", yourAction) where yourAction is your current performer, but implements javax.swing.Action. Done this way, threading should no longer be problem for switching. Verified in build 200309220100. Is there a way to listen to creation of new TopComponent's? If so, then of course that is the preferred technique. Ideally, I guess, the ActionMap of a TopComponent would be composed from some layer context, so that search module could register e.g. "TopComponentActions/org.openide.explorer.ExplorerPanel": "C-F" -> instance of SearchAction Then no listener would be needed; the TC would look for appropriate bindings when it was created. FYI: The code was rewritten to the new ActionMap system (as suggested by jtulach) as a part of fix of bug #56993. |