Bug 282333 - [examples] prestartup example should provide a UI-safe progress monitor to P2Util
Summary: [examples] prestartup example should provide a UI-safe progress monitor to P2...
Status: VERIFIED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: p2 (show other bugs)
Version: 3.5   Edit
Hardware: PC Mac OS X - Carbon (unsup.)
: P3 normal with 4 votes (vote)
Target Milestone: 3.6 RC3   Edit
Assignee: Susan McCourt CLA
QA Contact:
URL:
Whiteboard:
Keywords: example
: 286839 (view as bug list)
Depends on:
Blocks:
 
Reported: 2009-07-02 21:03 EDT by Jeff Norris CLA
Modified: 2010-08-05 12:47 EDT (History)
14 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jeff Norris CLA 2009-07-02 21:03:13 EDT
Build id: 20090619-0625

I'm using P2Util from the prestartupdate example.  If you pass a monitor into the engine.perform method, ie:

IStatus status = engine.perform(profile, new DefaultPhaseSet(), plan.getOperands(), pc, sub.newChild(100, SubMonitor.SUPPRESS_ALL_LABELS));

Then later the worker threads responsible for downloading the files will attempt to update the progress bar.  This causes an invalid thread access because these workers aren't in the UI thread.  An easy workaround is simply not to pass a monitor into the engine.perform method.  Stack trace below.

Thread [Worker-0] (Suspended (exception SWTException))	
	SWT.error(int, Throwable, String) line: 3886	
	SWT.error(int, Throwable) line: 3799	
	SWT.error(int) line: 3770	
	ProgressBar(Widget).error(int) line: 696	
	ProgressBar(Widget).checkWidget() line: 341	
	ProgressBar.getSelection() line: 153	
	ProgressIndicator.worked(double) line: 139	
	ProgressMonitorDialog$ProgressMonitor.internalWorked(double) line: 246	
	ProgressMonitorDialog$ProgressMonitor.worked(int) line: 241	
	SubMonitor$RootInfo.worked(int) line: 284	
	SubMonitor.internalWorked(double) line: 570	
	SubMonitor.worked(int) line: 585	
	FileReader.handleTransferEvent(IFileTransferEvent) line: 161	
	UrlConnectionRetrieveFileTransfer(AbstractRetrieveFileTransfer).fireTransferReceiveDataEvent() line: 318	
	UrlConnectionRetrieveFileTransfer(AbstractRetrieveFileTransfer).handleReceivedData(byte[], int, double, IProgressMonitor) line: 213	
	AbstractRetrieveFileTransfer$1.performFileTransfer(IProgressMonitor) line: 141	
	FileReader(FileTransferJob).run(IProgressMonitor) line: 73	
	Worker.run() line: 55
Comment 1 John Arthorne CLA 2009-07-06 00:54:25 EDT
I'm guessing you are calling ProgressMonitorDialog#run with fork=false, which assumes the operation is running entirely in the calling thread. I'm not sure what the right answer is here - you should generally be using fork=true if possible, which would avoid this problem. 

However, we're doing something a bit unusual here in p2, by reporting progress in a different thread from the one in which we were called. The IProgressMonitor contract doesn't disallow this, but maybe it should.
Comment 2 Susan McCourt CLA 2009-07-06 11:40:08 EDT
(In reply to comment #1)

> However, we're doing something a bit unusual here in p2, by reporting progress
> in a different thread from the one in which we were called. The
> IProgressMonitor contract doesn't disallow this, but maybe it should.
> 

See also a similar issue in bug 244246.  This bug was a bit different because there was code getting a UI-based progress monitor and passing it to a job.  However it's a similar issue.  Who is responsible for making sure a progress monitor is safe to call outside of the UI thread?  At the very least, p2 should document if the caller is supposed to ensure this.

Marking this as an [engine] bug for this particular case, but I think it's relevant to any API in p2 that accepts a progress monitor.

Comment 3 Simon Kaegi CLA 2009-07-06 12:31:25 EDT
I can't think how this wouldn't be the callers responsibility unless otherwise documented.

Is there a non UI-thread progress monitor that we can use to synch back progress results to a UI thread?
Comment 4 John Arthorne CLA 2009-07-06 12:35:09 EDT
Yes, the AccumulatingProgressMonitor in ModalContext gathers and dispatches progress updates to the UI thread. This is what is used in most cases, except here I am assuming they are using fork=false that would prevent the ModalContext gathering monitor to be used.
Comment 5 Ralf Ebert CLA 2009-10-24 14:14:29 EDT
Did anybody find a workaround to use P2Util and leave the progress monitoring intact despite this bug?

I just extracted the RCP auto update code into a separate plug-in so I can use it out of the box:
http://github.com/ralfebert/org.eclipse.equinox.p2.autoupdate

As part of this, I had to disable the progress monitoring, because it broke the file transfers:
http://github.com/ralfebert/org.eclipse.equinox.p2.autoupdate/commit/add1547f03480fc1dd0e2f5fa3394345be927c7d

Any ideas about this?
Comment 6 Susan McCourt CLA 2009-10-24 18:16:27 EDT
AccumulatingProgressMonitor would be the right thing to use here, but unfortunately it's only package visible in JFace.  You could make a copy of it, or you could provide a (non-accumulating) simpler wrapper that dispatches everything through an async exec.  Something like...

IProgressMonitor uiSafeMonitor = new ProgressMonitorWrapper(monitor) {
   // every method gets wrapped in an async, like this...
   public void worked(int work) {
      display.asyncExec(new Runnable() {
         public void run() {
            super.worked(work);
         }
      };
  }
};

then this monitor is handed to the engine.
For that matter, it should probably be used for the entire runnable with progress.

I'll update the example to do this (in M4), but this should get you going.
Comment 7 Ralf Ebert CLA 2009-10-24 19:29:52 EDT
Thanks for the workaround, I'll try this. For the moment the non-progressing progress monitor works fine as well :)

btw: Maybe it would make sense to distribute a "org.eclipse.equinox.p2.autoupdate" bundle that contains the P2Util class and the Activator code as official plug-in? In my opinion this would be very helpful for RCP developers as headless update is very often required for RCP applications.

btw: I just did a little tutorial about "p2 updates for Eclipse RCP applications" for my upcoming updated RCP training course materials:
http://www.ralfebert.de/blog/eclipsercp/p2_updates_tutorial/
Comment 8 Susan McCourt CLA 2009-11-12 17:00:14 EST
Hmmmm....I just reexamined this code as part of updating P2Util for bug 292907, and I don't really understand why the progress dialog is failing.  It is using a modal context with fork=true under the covers.  So something stranger is going on here than I first thought.  Will need to rebuild the example and investigate further.

> btw: Maybe it would make sense to distribute a
> "org.eclipse.equinox.p2.autoupdate" bundle that contains the P2Util class and
> the Activator code as official plug-in? In my opinion this would be very
> helpful for RCP developers as headless update is very often required for RCP
> applications.

We are looking at providing a headless p2 operations API (see bug 292907 and bug 292996) and this has reduced P2Util to about 10 lines of code.  The RCP app really needs to be the one deciding when to check (ie, prestartup in the workbench advisor) and what kind of progress reporting is desired.  So I don't see the need to support P2Util now that we've encapsulated all the low level code into a simple UpdateOperation.
Comment 9 Ralf Ebert CLA 2009-12-05 05:05:54 EST
For 3.5, the patched P2Util class with disabled progress monitoring works fine so far. Do you have an example of the 10 lines of P2Util code required to do this using the new API? I'd be willing to give it a try to make sure it suffices the RCP use case... Still, it would be worth considering a one-line solution (like a flag in WorkbenchAdvisor) to activate P2 updates for RCP applications imo.
Comment 10 Susan McCourt CLA 2009-12-07 11:48:44 EST
Take a look at P2Util (in the same prestartupdate example) in the branch called R3_6_api_cleanup.  Note that it runs against the p2 bundles from the branch.  We're hoping to merge back into HEAD early in M5.
Comment 11 Susan McCourt CLA 2010-01-28 13:51:04 EST
(In reply to comment #9)
> For 3.5, the patched P2Util class with disabled progress monitoring works fine
> so far. Do you have an example of the 10 lines of P2Util code required to do
> this using the new API? I'd be willing to give it a try to make sure it
> suffices the RCP use case... Still, it would be worth considering a one-line
> solution (like a flag in WorkbenchAdvisor) to activate P2 updates for RCP
> applications imo.

Ralf, the new API (and corresponding example changes) has been merged into HEAD and is available now in Eclipse 3.6 M5.
Comment 12 Susan McCourt CLA 2010-03-23 10:10:57 EDT
(In reply to comment #8)
> Hmmmm....I just reexamined this code as part of updating P2Util for bug 292907,
> and I don't really understand why the progress dialog is failing.  It is using
> a modal context with fork=true under the covers.  So something stranger is
> going on here than I first thought.  Will need to rebuild the example and
> investigate further.

Ian and I looked at this a little bit last night.
The problem is that the update check is happening at the wrong time in the workbench/workbench window startup sequence.  The event loop has not been started yet, so ModalContext.run(...) does not honor the fork=true, and therefore does not provide a UI-safe progress monitor.

The solution is to check for updates after the event loop is running.
I need to examine the startup sequence closer to be sure,  but something like WorkbenchWindowAdvisor.postWindowOpen
Comment 13 Susan McCourt CLA 2010-04-30 18:07:30 EDT
not sure which milestone yet, bugs first, then examples...
Comment 14 Susan McCourt CLA 2010-05-26 12:20:43 EDT
fixed in HEAD >20100526.
Moved the update check to postWindowOpen() on the workbench window advisor.

I also updated the product file to start ds so that the services could be found.  Without this, the operation was not finding a profile registry.

I also added a preference check so that when the app is restarting after an update, it won't check for updates again.
Comment 15 Susan McCourt CLA 2010-06-02 20:24:23 EDT
verified in Build id: I20100601-0800 via source inspection.
However I noticed that we aren't tagging the examples since they aren't in the map file.  Opened bug 315519 for this.
Comment 16 Susan McCourt CLA 2010-08-05 12:47:22 EDT
*** Bug 286839 has been marked as a duplicate of this bug. ***