Bug 578867 - report first (non system) job of family to block

Change-Id: I609094e0a70ab444bf0b748180f7b47bf958ac84
Signed-off-by: Joerg Kubitz <jkubitz-eclipse@gmx.de>
Reviewed-on: https://git.eclipse.org/r/c/platform/eclipse.platform.runtime/+/191004
Tested-by: Platform Bot <platform-bot@eclipse.org>
diff --git a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java b/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java
index 90dc5de..011c1f8 100644
--- a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java
+++ b/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/JobManager.java
@@ -946,16 +946,12 @@
 		IJobChangeListener listener = null;
 		final Set<InternalJob> jobs;
 		int jobCount;
-		Job blocking = null;
 		synchronized (lock) {
 			//don't join a waiting or sleeping job when suspended (deadlock risk)
 			int states = suspended ? Job.RUNNING : Job.RUNNING | Job.WAITING | Job.SLEEPING;
 			jobs = Collections.synchronizedSet(new HashSet<>(select(family, states)));
 			jobCount = jobs.size();
 			if (jobCount > 0) {
-				//if there is only one blocking job, use it in the blockage callback below
-				if (jobCount == 1)
-					blocking = (Job) jobs.iterator().next();
 				listener = new JobChangeAdapter() {
 					@Override
 					public void done(IJobChangeEvent event) {
@@ -1009,10 +1005,18 @@
 		try {
 			monitor.beginTask(JobMessages.jobs_blocked0, jobCount);
 			monitor.subTask(getWaitMessage(jobCount));
-			reportBlocked(monitor, blocking);
 			int jobsLeft;
 			int reportedWorkDone = 0;
+			List<InternalJob> reportedBlockingJobs = List.of();
 			while ((jobsLeft = jobs.size()) > 0) {
+				List<InternalJob> blockingJobs;
+				synchronized (jobs) {
+					blockingJobs = new ArrayList<>(jobs);
+				}
+				if (!Objects.equals(reportedBlockingJobs, blockingJobs)) {
+					reportBlocked(monitor, blockingJobs);
+					reportedBlockingJobs = blockingJobs;
+				}
 				//don't let there be negative work done if new jobs have
 				//been added since the join began
 				int actualWorkDone = Math.max(0, jobCount - jobsLeft);
@@ -1212,16 +1216,19 @@
 	}
 
 	/**
-	 * Report to the progress monitor that this thread is blocked, supplying
-	 * an information message, and if possible the job that is causing the blockage.
-	 * Important: An invocation of this method MUST be followed eventually be
-	 * an invocation of reportUnblocked.
-	 * @param monitor The monitor to report blocking to
-	 * @param blockingJob The job that is blocking this thread, or <code>null</code>
+	 * Report to the progress monitor that this thread is blocked, supplying an
+	 * information message, and if possible jobs that are causing the blockage.
+	 * Important: An invocation of this method MUST be followed eventually be an
+	 * invocation of reportUnblocked.
+	 *
+	 * @param monitor      The monitor to report blocking to
+	 * @param blockingJobs The jobs that are blocking this thread
 	 * @see #reportUnblocked
 	 */
-	final void reportBlocked(IProgressMonitor monitor, InternalJob blockingJob) {
+	final void reportBlocked(IProgressMonitor monitor, List<InternalJob> blockingJobs) {
 		IStatus reason;
+		InternalJob blockingJob = blockingJobs.stream().sorted(Comparator.comparing(InternalJob::isSystem)).findFirst()
+				.orElse(null);
 		if (blockingJob == null || blockingJob instanceof ThreadJob || blockingJob.isSystem()) {
 			reason = new Status(IStatus.INFO, JobManager.PI_JOBS, 1, JobMessages.jobs_blocked0, null);
 		} else {
diff --git a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/ThreadJob.java b/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/ThreadJob.java
index df47189..6ed718f 100644
--- a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/ThreadJob.java
+++ b/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/ThreadJob.java
@@ -13,6 +13,7 @@
  *******************************************************************************/
 package org.eclipse.core.internal.jobs;
 
+import java.util.List;
 import org.eclipse.core.internal.runtime.RuntimeLog;
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.jobs.*;
@@ -507,7 +508,7 @@
 	 */
 	static private void waitStart(ThreadJob threadJob, IProgressMonitor monitor, InternalJob blockingJob) {
 		threadJob.isBlocked = true;
-		manager.reportBlocked(monitor, blockingJob);
+		manager.reportBlocked(monitor, blockingJob == null ? List.of() : List.of(blockingJob));
 	}
 
 	/**