Community
Participate
Working Groups
Create some code - it has 2 parts one is running in UI and one is code running in background. Call background code: workbench.getProgressService().busyCursorWhile(this); UI code is just updating user interface [-; Let's imagine that the background code has some synchronized section. It enters this synchronized section, and provides feedback to user using progress monitor. This synchronized is long running action. Also background thread/some other thread sent before/during background sync section some stuff to UI which also acquires this background thread lock. So what's the problem - when calling progress monitor AccumulatingProgressMonitor - this class acquires RunnableLock, but this RunnableLock has already been acquired by other UI runner (Display.asyncExec) when there was something to be sent to UI. The problem is generally about UI sync/asyncexec rules. I think that main problem is that AccumulatingProgressMonitor uses Display.syncExec in some parts. I think that any progressmonitor shouldn't acquire any lock and also shouldn't block processing anyhow, because this can cause such pains.
I have put some my thoughts about this problem to my blog: http://www.puakma.net/puakma/martinplog.pma/ViewEntry?OpenPage&ID=14
I see your issue - the problem is that asyncExecs can happen at any time - if we switch to them you can potentialy get updates at strange times which may also include behaviour like monitors moving backwards. I don't think that switching to asyncExecs is a safe answer - not locking the Ui Thread is. The lack of updates from the progress monitor is only your first symptom - the generally prevention of updates in the UI is something t be avoided.
Actually I think I want to think out this more. As asyncExecs are ordered I think it may be safe to do something using them instead of syncExecs in this case. I still think you need to be very careful with code in synchronized blocks calling out to the UI in using syncExecs. We can reduce the danger of this by reducing out use of syncExec but we are only one place where you could run into trouble with this.
Changing OS from Mac OS to Mac OS X as per bug 185991
I've got an actual deadlock (bug 203306) due to this issue, and I have seen similar deadlocks before, and now I understand why this happens. The problems are, that 1.) My client has to lock a single shared resource, 2.) I do want to provide progress reporting while holding on to it, 3.) Being an open Framework I cannot avoid being called by others on the UI thread (and needing the shared resource there) With the IProgressMonitor, one is not easily aware of the fact that progress reporting calls out into the UI and may actually block there. I whole-heartedly agree with Martin saying that any kind of progress reporting should never block. I'm actually thinking about writing an AsyncProgressMonitor wrapper to work around my situation, where my wrapper would ensure that the wrapped monitor is always called asynchronously. This is problematic though, because I cannot easily decouple from isCanceled(); and, it would be a workaround for my concrete situation only, whereas switching to asyncExec in core Eclipse everywhere would fix it once and for all. I agree that because asyncExecs are ordered, there is no threat of mixing things up - actually, using ONLY asyncExecs may be safer than a mixture of syncExec and asyncExec.
It's also interesting to note that when it comes to progress reporting in the Job framework, all calls are synchronous without UI until it comes to a progress listener; the progress listener gives UI feedback, e.g. through ProgressMonitorFocusJobDialog#getBlockingProgressMonitor() which always does runAsync().
Fixed for build >20071011
Verified in I20071029-0100