Bug 238397 [Commands] Concurrent modification possible in DefaultOperationHistory
Build ID: 3.3.3.r33x_r20080129 Steps To Reproduce: This is kind of hard to reproduce, nevertheless the systematic gap can be seen directly within the coding. Please have a look into the coding of the method flushUndo(...) in org.eclipse.core.commands.operations.DefaultOperationHistory. The undoList.remove is triggered without any synchronization (in contrast to the other coding locations the list is modified). This may lead to ConcurrentModificationExceptions in case of very rapidly fired Undo/redo events (in fact that's what happended within one of our automated tests). Furthermore, the method filter(...) called right before the for-loop first gets an iterator for the list, then aquires the lock an then loops over the iterator. In rare cases this may lead to IndexOutOfBoundsExceptions when another thread modified the list in between getting the iterator and looping over it (actually also this happened in the mentioned test case). From my point of view the lock should already by aquired in the flushUndo before calling the filter(...) method. More information: I'm sorry for not being able to offer a reproducable code snippet, since our case we spotted this needs a quite complicated setup, a lot of testdata and used quite a lot of parallel threading.
bundles/org.eclipse.core.commands/src/org/eclipse/core/commands/operations/DefaultOperationHistory.java
* (non-Javadoc)
	 * 
	 * @see org.eclipse.core.commands.operations.IOperationHistory#removeOperationApprover(org.eclipse.core.commands.operations.IOperationApprover)
	 */
	public void removeOperationApprover(IOperationApprover approver) {
		approvers.remove(approver);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.commands.operations.IOperationHistory#removeOperationHistoryListener(org.eclipse.core.commands.operations.IOperationHistoryListener)
	 */
	public void removeOperationHistoryListener(
			IOperationHistoryListener listener) {
		listeners.remove(listener);
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.commands.operations.IOperationHistory#replaceOperation(org.eclipse.core.commands.operations.IUndoableOperation,
	 *      org.eclipse.core.commands.operations.IUndoableOperation [])
	 */
	public void replaceOperation(IUndoableOperation operation,
			IUndoableOperation[] replacements) {
		
		boolean inUndo = false;
		synchronized (undoRedoHistoryLock) {
			int index = undoList.indexOf(operation);
			if (index > -1) {
				inUndo = true;