Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 296056 | Differences between
and this patch

Collapse All | Expand All

(-)Eclipse (+109 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.ui.tests.concurrency;
13
14
import junit.framework.TestCase;
15
import org.eclipse.core.runtime.SubMonitor;
16
import org.eclipse.core.runtime.jobs.ISchedulingRule;
17
import org.eclipse.core.runtime.jobs.Job;
18
import org.eclipse.swt.SWTException;
19
import org.eclipse.swt.widgets.Display;
20
21
/**
22
 * This tests the simple traditional deadlock of a thread holding a scheduling rule trying
23
 * to perform a syncExec, while the UI thread is waiting for that scheduling rule.
24
 * UISynchronizer and UILockListener conspire to prevent deadlock in this case.
25
 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=296056.
26
 */
27
public class SyncExecWhileUIThreadWaitsForRuleTest extends TestCase {
28
	class TestRule implements ISchedulingRule {
29
		public boolean contains(ISchedulingRule rule) {
30
			return rule == this;
31
		}
32
33
		public boolean isConflicting(ISchedulingRule rule) {
34
			return rule == this;
35
		}
36
	}
37
38
	public void testDeadlock() {
39
		final ISchedulingRule rule = new TestRule();
40
		final boolean[] blocked = new boolean[] {false};
41
		final boolean[] lockAcquired = new boolean[] {false};
42
		final SubMonitor beginRuleMonitor = SubMonitor.convert(null);
43
		Thread locking = new Thread("SyncExecWhileUIThreadWaitsForRuleTest") {
44
			public void run() {
45
				try {
46
					//first make sure this background thread owns the lock
47
					Job.getJobManager().beginRule(rule, null);
48
					//spawn an asyncExec that will cause the UI thread to be blocked
49
					Display.getDefault().asyncExec(new Runnable() {
50
						public void run() {
51
							blocked[0] = true;
52
							Job.getJobManager().beginRule(rule, beginRuleMonitor);
53
							Job.getJobManager().endRule(rule);
54
							blocked[0] = false;
55
						}
56
					});
57
					//wait until the UI thread is blocked waiting for the lock
58
					while (!blocked[0]) {
59
						try {
60
							Thread.sleep(100);
61
						} catch (InterruptedException e) {
62
							e.printStackTrace();
63
						}
64
					}
65
					//now attempt to do a syncExec that also acquires the lock
66
					//this should succeed even while the above asyncExec is blocked, thanks to UISynchronizer
67
					Display.getDefault().syncExec(new Runnable() {
68
						public void run() {
69
							//use a timeout to avoid deadlock in case of regression
70
							Job.getJobManager().beginRule(rule, null);
71
							lockAcquired[0] = true;
72
							Job.getJobManager().endRule(rule);
73
						}
74
					});
75
				} finally {
76
					Job.getJobManager().endRule(rule);
77
				}
78
			}
79
		};
80
		locking.start();
81
		//create a thread that will cancel the monitor after 60 seconds so we don't hang the tests
82
		final long waitStart = System.currentTimeMillis();
83
		Thread canceler = new Thread("Canceler") {
84
			public void run() {
85
				while (true) {
86
					if (System.currentTimeMillis() - waitStart > 60000) {
87
						beginRuleMonitor.setCanceled(true);
88
						break;
89
					}
90
				}
91
92
			}
93
		};
94
		canceler.start();
95
		//wait until we succeeded to acquire the lock in the UI thread
96
		Display display = Display.getDefault();
97
		while (!lockAcquired[0]) {
98
			//spin event loop so that asyncExed above gets run
99
			try {
100
				if (!display.readAndDispatch())
101
					display.sleep();
102
			} catch (SWTException e) {
103
				fail("Deadlock occurred");
104
			}
105
		}
106
		//if the monitor was canceled then we got a deadlock
107
		assertFalse("deadlock occurred", beginRuleMonitor.isCanceled());
108
	}
109
}

Return to bug 296056