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 265324
Collapse All | Expand All

(-)a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/DeadlockDetector.java (-9 / +17 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2012 IBM Corporation and others.
2
 * Copyright (c) 2003, 2013 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 184-200 Link Here
184
	/**
184
	/**
185
	 * Returns all the locks owned by the given thread
185
	 * Returns all the locks owned by the given thread
186
	 */
186
	 */
187
	private Object[] getOwnedLocks(Thread current) {
187
	ISchedulingRule[] getOwnedLocks(Thread thread) {
188
		return getOwnedLocks(thread, false);
189
	}
190
191
	/**
192
	 * Returns all the locks owned by the given thread
193
	 */
194
	private ISchedulingRule[] getOwnedLocks(Thread current, boolean deadlocked) {
188
		ArrayList ownedLocks = new ArrayList(1);
195
		ArrayList ownedLocks = new ArrayList(1);
189
		int index = indexOf(current, false);
196
		int index = indexOf(current, false);
190
197
		if (index >= 0) {
191
		for (int j = 0; j < graph[index].length; j++) {
198
			for (int j = 0; j < graph[index].length; j++) {
192
			if (graph[index][j] > NO_STATE)
199
				if (graph[index][j] > NO_STATE)
193
				ownedLocks.add(locks.get(j));
200
					ownedLocks.add(locks.get(j));
201
			}
194
		}
202
		}
195
		if (ownedLocks.size() == 0)
203
		if (deadlocked && ownedLocks.size() == 0)
196
			Assert.isLegal(false, "A thread with no locks is part of a deadlock."); //$NON-NLS-1$
204
			Assert.isLegal(false, "A thread with no locks is part of a deadlock."); //$NON-NLS-1$
197
		return ownedLocks.toArray();
205
		return (ISchedulingRule[]) ownedLocks.toArray(new ISchedulingRule[ownedLocks.size()]);
198
	}
206
	}
199
207
200
	/**
208
	/**
Lines 599-605 Link Here
599
		MultiStatus main = new MultiStatus(JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, new IllegalStateException());
607
		MultiStatus main = new MultiStatus(JobManager.PI_JOBS, JobManager.PLUGIN_ERROR, msg, new IllegalStateException());
600
		Thread[] threads = deadlock.getThreads();
608
		Thread[] threads = deadlock.getThreads();
601
		for (int i = 0; i < threads.length; i++) {
609
		for (int i = 0; i < threads.length; i++) {
602
			Object[] ownedLocks = getOwnedLocks(threads[i]);
610
			Object[] ownedLocks = getOwnedLocks(threads[i], true);
603
			Object waitLock = getWaitingLock(threads[i]);
611
			Object waitLock = getWaitingLock(threads[i]);
604
			StringBuffer buf = new StringBuffer("Thread "); //$NON-NLS-1$
612
			StringBuffer buf = new StringBuffer("Thread "); //$NON-NLS-1$
605
			buf.append(threads[i].getName());
613
			buf.append(threads[i].getName());
(-)a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/LockManager.java (-1 / +15 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 *  Copyright (c) 2003, 2012 IBM Corporation and others.
2
 *  Copyright (c) 2003, 2013 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
5
 *  which accompanies this distribution, and is available at
Lines 177-182 Link Here
177
		}
177
		}
178
	}
178
	}
179
179
180
	ISchedulingRule[] getOwnedLocks(Thread thread) {
181
		DeadlockDetector tempLocks = locks;
182
		if (tempLocks == null)
183
			return null;
184
		try {
185
			synchronized (tempLocks) {
186
				return tempLocks.getOwnedLocks(thread);
187
			}
188
		} catch (Exception e) {
189
			handleInternalError(e);
190
		}
191
		return null;
192
	}
193
180
	/**
194
	/**
181
	 * Handles exceptions that occur while calling third party code from within the
195
	 * Handles exceptions that occur while calling third party code from within the
182
	 * LockManager. This is essentially an in-lined version of Platform.run(ISafeRunnable)
196
	 * LockManager. This is essentially an in-lined version of Platform.run(ISafeRunnable)
(-)a/bundles/org.eclipse.core.jobs/src/org/eclipse/core/internal/jobs/WorkerPool.java (-4 / +36 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 *  Copyright (c) 2003, 2012 IBM Corporation and others.
2
 *  Copyright (c) 2003, 2013 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
5
 *  which accompanies this distribution, and is available at
Lines 10-18 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.core.internal.jobs;
11
package org.eclipse.core.internal.jobs;
12
12
13
import org.eclipse.core.runtime.Assert;
13
import org.eclipse.core.internal.runtime.RuntimeLog;
14
import org.eclipse.core.runtime.IStatus;
14
import org.eclipse.core.runtime.*;
15
import org.eclipse.core.runtime.jobs.Job;
15
import org.eclipse.core.runtime.jobs.*;
16
16
17
/**
17
/**
18
 * Maintains a pool of worker threads. Threads are constructed lazily as
18
 * Maintains a pool of worker threads. Threads are constructed lazily as
Lines 81-86 Link Here
81
		threads[numThreads++] = worker;
81
		threads[numThreads++] = worker;
82
	}
82
	}
83
83
84
	private void cleanWorker(InternalJob job) {
85
		//there should be no locks owned by the current thread at this moment, release if there are any left
86
		ISchedulingRule[] locks = manager.getLockManager().getOwnedLocks(Thread.currentThread());
87
		if (locks != null && locks.length > 0) {
88
			String msg = "Worker thread ended job: " + job + ", but still holds locks: ["; //$NON-NLS-1$ //$NON-NLS-2$
89
			for (int i = 0; i < locks.length; i++) {
90
				//it is allowed to call ILock#release here because it is called in the same thread in
91
				//which job was running but failed to release the lock in its Job#run method
92
				//it is still a bug in client code that they failed to release the lock, but to avoid
93
				//a deadlock we release it for them
94
				if (locks[i] instanceof ILock) {
95
					ILock lock = (ILock) locks[i];
96
					int depth = lock.getDepth();
97
					for (int j = 0; j < depth; j++)
98
						lock.release();
99
				}
100
				msg += locks[i].toString();
101
				if (i < locks.length - 1)
102
					msg += ","; //$NON-NLS-1$
103
			}
104
			msg += "]"; //$NON-NLS-1$
105
			IStatus error = new Status(IStatus.ERROR, JobManager.PI_JOBS, 1, msg, null);
106
			try {
107
				RuntimeLog.log(error);
108
			} catch (RuntimeException e) {
109
				//failed to log, so print to console instead
110
				System.err.println(error.getMessage());
111
			}
112
		}
113
	}
114
84
	private synchronized void decrementBusyThreads() {
115
	private synchronized void decrementBusyThreads() {
85
		//impossible to have less than zero busy threads
116
		//impossible to have less than zero busy threads
86
		if (--busyThreads < 0) {
117
		if (--busyThreads < 0) {
Lines 106-111 Link Here
106
			//ensure this thread no longer owns any scheduling rules
137
			//ensure this thread no longer owns any scheduling rules
107
			manager.implicitJobs.endJob(job);
138
			manager.implicitJobs.endJob(job);
108
		} finally {
139
		} finally {
140
			cleanWorker(job);
109
			decrementBusyThreads();
141
			decrementBusyThreads();
110
		}
142
		}
111
	}
143
	}
(-)a/tests/org.eclipse.core.tests.runtime/src/org/eclipse/core/tests/runtime/jobs/IJobManagerTest.java (-1 / +40 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2012 IBM Corporation and others.
2
 * Copyright (c) 2003, 2013 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 137-142 Link Here
137
		//		manager.startup();
137
		//		manager.startup();
138
	}
138
	}
139
139
140
	/**
141
	 * Tests running a job that acquires a lock but never releases it
142
	 */
143
	public void testAcquireLockNoRelease() {
144
		final ILock lock1 = manager.newLock();
145
		final ILock lock2 = manager.newLock();
146
		Job job = new Job("testAcquireLockNoRelease") {
147
			protected IStatus run(IProgressMonitor monitor) {
148
				monitor.beginTask(getName(), 1);
149
				try {
150
					lock1.acquire();
151
					lock1.acquire();
152
					lock1.acquire();
153
					lock2.acquire();
154
					monitor.worked(1);
155
				} finally {
156
					monitor.done();
157
				}
158
				return Status.OK_STATUS;
159
			}
160
		};
161
		job.schedule();
162
		try {
163
			job.join();
164
		} catch (InterruptedException e) {
165
			fail("1.0", e);
166
		}
167
		//another thread should be able to acquire the lock now
168
		try {
169
			assertTrue("2.1", lock1.acquire(10000));
170
			assertTrue("2.2", lock2.acquire(10000));
171
		} catch (InterruptedException e) {
172
			fail("3.0", e);
173
		} finally {
174
			lock1.release();
175
			lock2.release();
176
		}
177
	}
178
140
	public void testBeginInvalidNestedRules() {
179
	public void testBeginInvalidNestedRules() {
141
		final ISchedulingRule root = new PathRule("/");
180
		final ISchedulingRule root = new PathRule("/");
142
		final ISchedulingRule invalid = new ISchedulingRule() {
181
		final ISchedulingRule invalid = new ISchedulingRule() {

Return to bug 265324