/*******************************************************************************
 * Copyright (c) 2010, 2017 TUBITAK BILGEM-ITI and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Onur Akdemir (TUBITAK BILGEM-ITI) - Multi-process debugging (Bug 237306)
 *     Marc Khouzam (Ericsson) - Workaround for Bug 352998
 *     Marc Khouzam (Ericsson) - Update breakpoint handling for GDB >= 7.4 (Bug 389945)
 *     Alvaro Sanchez-Leon (Ericsson) - Breakpoint Enable does not work after restarting the application (Bug 456959)
 *******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.cdt.debug.core.CDebugUtils;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Sequence;
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryDMContext;
import org.eclipse.cdt.dsf.debug.service.IMultiDetach;
import org.eclipse.cdt.dsf.debug.service.IMultiTerminate;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ICreatedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.launching.GDBRemoteTCPLaunchTargetProvider;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIRunControl;
import org.eclipse.cdt.dsf.mi.service.IMIRunControl.MIRunMode;
import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager;
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.events.MIThreadGroupAddedEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIAddInferiorInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.launchbar.core.target.ILaunchTarget;
import org.eclipse.launchbar.core.target.launch.ITargetedLaunch;

import com.ibm.icu.text.MessageFormat;

/**
 * Adding support for multi-process with GDB 7.2
 *
 * @since 4.0
 */
public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminate, IMultiDetach {

	abstract private class ConditionalRequestMonitor extends ImmediateDataRequestMonitor<Boolean> {

		private Iterator<? extends IDMContext> fIterator;
		private boolean fAll = true;
		private DataRequestMonitor<Boolean> fParentMonitor;

		private ConditionalRequestMonitor(Iterator<? extends IDMContext> it, boolean all,
				DataRequestMonitor<Boolean> parentMonitor) {
			super(parentMonitor);
			fAll = all;
			fParentMonitor = parentMonitor;
			fIterator = it;
		}

		@Override
		protected void handleCompleted() {
			if (!isSuccess()) {
				fParentMonitor.setStatus(getStatus());
				fParentMonitor.done();
				return;
			}

			if (getData() != fAll) {
				fParentMonitor.setData(getData());
				fParentMonitor.done();
			} else if (!fIterator.hasNext()) {
				fParentMonitor.setData(fAll);
				fParentMonitor.done();
			} else {
				proceed(fIterator, fAll, fParentMonitor);
			}
		}

		abstract protected void proceed(Iterator<? extends IDMContext> it, boolean all,
				DataRequestMonitor<Boolean> parentMonitor);
	}

	private class CanDetachRequestMonitor extends ConditionalRequestMonitor {

		private CanDetachRequestMonitor(Iterator<? extends IDMContext> it, boolean all,
				DataRequestMonitor<Boolean> parentMonitor) {
			super(it, all, parentMonitor);
		}

		@Override
		protected void proceed(Iterator<? extends IDMContext> it, boolean all,
				DataRequestMonitor<Boolean> parentMonitor) {
			canDetachDebuggerFromProcess(it.next(), new CanDetachRequestMonitor(it, all, parentMonitor));
		}

	}

	private class CanTerminateRequestMonitor extends ConditionalRequestMonitor {

		private CanTerminateRequestMonitor(Iterator<? extends IDMContext> it, boolean all,
				DataRequestMonitor<Boolean> parentMonitor) {
			super(it, all, parentMonitor);
		}

		@Override
		protected void proceed(Iterator<? extends IDMContext> it, boolean all,
				DataRequestMonitor<Boolean> parentMonitor) {
			canTerminate((IThreadDMContext) it.next(), new CanTerminateRequestMonitor(it, all, parentMonitor));
		}
	}

	/**
	 * Event indicating that a container (gdb inferior) has been created, but is not yet running.
	 * @since 5.1
	 */
	protected static class ContainerCreatedDMEvent extends AbstractDMEvent<IExecutionDMContext>
			implements ICreatedDMEvent {
		public ContainerCreatedDMEvent(IContainerDMContext context) {
			super(context);
		}
	}

	/**
	 * The first thread-group id used by GDB.
	 * GDB starts up with certain things already setup, and we need
	 * to prepare some things using this id.
	 * @since 5.1
	 */
	public static final String INITIAL_THREAD_GROUP_ID = "i1"; //$NON-NLS-1$

	/**
	 * The id of the single thread to be used during event visualization.
	 * @since 4.1
	 */
	protected static final String TRACE_VISUALIZATION_THREAD_ID = "1"; //$NON-NLS-1$

	private CommandFactory fCommandFactory;
	private IGDBControl fCommandControl;
	private IGDBBackend fBackend;

	private final static String INVALID = "invalid"; //$NON-NLS-1$

	/**
	 * Keep track if we need to reconnect to the target
	 * due to a workaround because of a GDB 7.2 bug.
	 * Bug 352998
	 */
	private boolean fNeedToReconnect;

	/**
	 * Set of processes that are currently being restarted.
	 * We use this set for such things as not removing breakpoints
	 * because we know the process will be restarted.
	 */
	private Set<IContainerDMContext> fProcRestarting = new HashSet<>();

	/**
	 * Indicates that we are currently visualizing trace data.
	 */
	private boolean fTraceVisualization;

	public GDBProcesses_7_2(DsfSession session) {
		super(session);
	}

	@Override
	public void initialize(final RequestMonitor requestMonitor) {
		super.initialize(new ImmediateRequestMonitor(requestMonitor) {
			@Override
			protected void handleSuccess() {
				doInitialize(requestMonitor);
			}
		});
	}

	/**
	 * This method initializes this service after our superclass's initialize()
	 * method succeeds.
	 *
	 * @param requestMonitor
	 *            The call-back object to notify when this service's
	 *            initialization is done.
	 */
	private void doInitialize(RequestMonitor requestMonitor) {
		register(new String[] { IMultiDetach.class.getName(), IMultiTerminate.class.getName() },
				new Hashtable<String, String>());

		fCommandControl = getServicesTracker().getService(IGDBControl.class);
		fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
		fBackend = getServicesTracker().getService(IGDBBackend.class);

		// We know we missed the very first =thread-group-added event
		// because GDB sends it as soon as it starts, but we are not
		// ready to receive it at that time.  We send it now instead.
		IMIContainerDMContext initialContainer = createContainerContextFromGroupId(fCommandControl.getContext(),
				INITIAL_THREAD_GROUP_ID);
		getSession().dispatchEvent(new ContainerCreatedDMEvent(initialContainer), getProperties());

		requestMonitor.done();
	}

	@Override
	public void shutdown(RequestMonitor requestMonitor) {
		super.shutdown(requestMonitor);
	}

	/** @since 4.1 */
	protected boolean getTraceVisualization() {
		return fTraceVisualization;
	}

	/** @since 4.1 */
	protected void setTraceVisualization(boolean visualizing) {
		fTraceVisualization = visualizing;
	}

	@Override
	public IMIContainerDMContext createContainerContextFromGroupId(ICommandControlDMContext controlDmc,
			String groupId) {
		String pid = getGroupToPidMap().get(groupId);
		if (pid == null) {
			// For GDB 7.2, the groupId is no longer the pid, so use our wildcard pid instead
			pid = MIProcesses.UNKNOWN_PROCESS_ID;
		}
		IProcessDMContext processDmc = createProcessContext(controlDmc, pid);
		return createContainerContext(processDmc, groupId);
	}

	@Override
	protected boolean doIsDebuggerAttachSupported() {
		// Multi-process is not applicable to post-mortem sessions (core)
		// or to non-attach remote sessions.
		if (fBackend.getSessionType() == SessionType.CORE) {
			return false;
		}

		if (fBackend.getSessionType() == SessionType.REMOTE && !fBackend.getIsAttachSession()) {
			return false;
		}

		// Multi-process does not work for all-stop right now
		IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class);
		if (runControl != null && runControl.getRunMode() == MIRunMode.ALL_STOP) {
			// Only one process is allowed in all-stop (for now)
			return getNumConnected() == 0;
			// NOTE: when we support multi-process in all-stop mode,
			// we will need to interrupt the target to when doing the attach.
		}

		return true;
	}

	@Override
	public void attachDebuggerToProcess(IProcessDMContext procCtx, DataRequestMonitor<IDMContext> rm) {
		attachDebuggerToProcess(procCtx, null, rm);
	}

	/**
	 * @since 4.0
	 */
	@Override
	public void attachDebuggerToProcess(final IProcessDMContext procCtx, final String binaryPath,
			final DataRequestMonitor<IDMContext> dataRm) {
		if (procCtx instanceof IMIProcessDMContext) {
			if (!doIsDebuggerAttachSupported()) {
				dataRm.setStatus(
						new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Attach not supported.", null)); //$NON-NLS-1$
				dataRm.done();
				return;
			}

			// Use a sequence for better control of each step
			ImmediateExecutor.getInstance().execute(new Sequence(getExecutor(), dataRm) {
				private IMIContainerDMContext fContainerDmc;

				private Step[] steps = new Step[] {
						// first check if requested process is already targetted
						new Step() {
							@Override
							public void execute(final RequestMonitor rm) {
								getProcessesBeingDebugged(procCtx, new ImmediateDataRequestMonitor<IDMContext[]>(rm) {
									@Override
									protected void handleSuccess() {
										assert getData() != null;

										boolean found = false;
										for (IDMContext dmc : getData()) {
											IProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc,
													IProcessDMContext.class);
											if (procCtx.equals(procDmc)) {
												found = true;
											}
										}
										if (found) {
											// abort the sequence
											Status failedStatus = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
													REQUEST_FAILED,
													MessageFormat.format(Messages.Already_connected_process_err,
															((IMIProcessDMContext) procCtx).getProcId()),
													null);
											rm.done(failedStatus);
											return;
										}
										super.handleSuccess();
									}
								});
							}
						},

						// If this is not the very first inferior, we first need create the new inferior
						new Step() {
							@Override
							public void execute(final RequestMonitor rm) {
								if (isInitialProcess()) {
									// If it is the first inferior, GDB has already created it for us
									// We really should get the id from GDB instead of hard-coding it
									fContainerDmc = createContainerContext(procCtx, INITIAL_THREAD_GROUP_ID);
									rm.done();
									return;
								}

								ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx,
										ICommandControlDMContext.class);
								fCommandControl.queueCommand(fCommandFactory.createMIAddInferior(controlDmc),
										new ImmediateDataRequestMonitor<MIAddInferiorInfo>(rm) {
											@Override
											protected void handleSuccess() {
												final String groupId = getData().getGroupId();
												if (groupId == null || groupId.trim().length() == 0) {
													rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
															INTERNAL_ERROR, "Invalid gdb group id.", null)); //$NON-NLS-1$
												} else {
													fContainerDmc = createContainerContext(procCtx, groupId);
												}
												rm.done();
											}
										});
							}
						}, new Step() {
							@Override
							public void execute(final RequestMonitor rm) {
								// Because of a GDB 7.2 bug, for remote-attach sessions,
								// we need to be disconnected from the target
								// when we set the very first binary to be used.
								// So, lets disconnect.
								// Bug 352998
								if (needFixForGDB72Bug352998()) {
									// The bug only applies to remote sessions
									if (fBackend.getSessionType() == SessionType.REMOTE) {
										assert fBackend.getIsAttachSession();
										assert binaryPath != null;

										// We only need the workaround for the very first process we attach to
										if (isInitialProcess()) {
											ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(procCtx,
													ICommandControlDMContext.class);
											fCommandControl.queueCommand(
													fCommandFactory.createMITargetDisconnect(controlDmc),
													new ImmediateDataRequestMonitor<MIInfo>(rm) {
														@Override
														protected void handleSuccess() {
															fNeedToReconnect = true;
															rm.done();
														}
													});
											return;
										}
									}
								}

								rm.done();
							}
						}, new Step() {
							@Override
							public void execute(final RequestMonitor rm) {
								// Now, set the binary to be used.
								if (binaryPath != null) {
									fCommandControl.queueCommand(
											fCommandFactory.createMIFileExecAndSymbols(fContainerDmc, binaryPath),
											new ImmediateDataRequestMonitor<MIInfo>(rm) {
												@Override
												protected void handleCompleted() {
													// Because of a GDB 7.2 bug, for remote-attach sessions,
													// we need to be disconnected from the target
													// when we set the very first binary to be used.
													// Now that we have disconnected and set the binary,
													// we may need to reconnect to the target.
													// If we were unable to set the binary (e.g., if the specified path
													// is invalid) we also need to reconnect to the target before
													// aborting the rest of the sequence.
													// Bug 352998

													if (fNeedToReconnect) {
														fNeedToReconnect = false;

														// Set the status in case it is an error, so that when rm.done() is automatically
														// called, we continue to abort the sequence if we are dealing with a failure.
														rm.setStatus(getStatus());

														connectToTarget(procCtx, rm);
													} else {
														super.handleCompleted();
													}
												}
											});
									return;
								}

								assert fNeedToReconnect == false;
								rm.done();
							}
						},
						// Now, actually do the attach
						new Step() {
							@Override
							public void execute(RequestMonitor rm) {
								// For non-stop mode, we do a non-interrupting attach
								// Bug 333284
								boolean shouldInterrupt = true;
								IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class);
								if (runControl != null && runControl.getRunMode() == MIRunMode.NON_STOP) {
									shouldInterrupt = false;
								}

								boolean extraNewline = targetAttachRequiresTrailingNewline();
								ICommand<MIInfo> miTargetAttach = fCommandFactory.createMITargetAttach(fContainerDmc,
										((IMIProcessDMContext) procCtx).getProcId(), shouldInterrupt, extraNewline);
								fCommandControl.queueCommand(miTargetAttach,
										new ImmediateDataRequestMonitor<MIInfo>(rm));
							}

						},
						// Initialize memory data for this process.
						new Step() {
							@Override
							public void execute(RequestMonitor rm) {
								IGDBMemory memory = getServicesTracker().getService(IGDBMemory.class);
								IMemoryDMContext memContext = DMContexts.getAncestorOfType(fContainerDmc,
										IMemoryDMContext.class);
								if (memory == null || memContext == null) {
									rm.done();
									return;
								}
								memory.initializeMemoryData(memContext, rm);
							}
						},
						// Start tracking this process' breakpoints.
						new Step() {
							@Override
							public void execute(RequestMonitor rm) {
								MIBreakpointsManager bpmService = getServicesTracker()
										.getService(MIBreakpointsManager.class);
								bpmService.startTrackingBpForProcess(fContainerDmc, rm);
							}
						},
						// Turn on reverse debugging if it was enabled as a launch option
						new Step() {
							@Override
							public void execute(RequestMonitor rm) {
								doReverseDebugStep(procCtx, rm);
							}
						},
						// Store the fully formed container context so it can be returned to the caller
						// and mark that we are not dealing with the first process anymore.
						new Step() {
							@Override
							public void execute(RequestMonitor rm) {
								dataRm.setData(fContainerDmc);
								setIsInitialProcess(false);

								rm.done();
							}
						}, };

				@Override
				public Step[] getSteps() {
					return steps;
				}
			});
		} else {
			dataRm.setStatus(
					new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid process context.", null)); //$NON-NLS-1$
			dataRm.done();
		}
	}

	/**
	 * GDB 7.11 had a bug that -target-attach sometimes did not flush its error
	 * response. However sending a newline forced GDB to flush the buffer.
	 *
	 * See Bug 522367
	 *
	 * @return whether to add extra newline.
	 * @since 5.4
	 */
	protected boolean targetAttachRequiresTrailingNewline() {
		return false;
	}

	private void connectToTarget(IProcessDMContext procCtx, RequestMonitor rm) {
		ILaunch launch = procCtx.getAdapter(ILaunch.class);
		assert launch != null;
		if (launch != null) {
			Map<String, Object> attributes = new HashMap<>();
			try {
				attributes.putAll(launch.getLaunchConfiguration().getAttributes());
			} catch (CoreException e) {
				rm.done(e.getStatus());
				return;
			}

			if (launch instanceof ITargetedLaunch) {
				ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
				if (target != null) {
					attributes.putAll(target.getAttributes());
					String tcp = target.getAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, ""); //$NON-NLS-1$
					if (!tcp.isEmpty()) {
						attributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, Boolean.parseBoolean(tcp));
					} else {
						attributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
								target.getTypeId().equals(GDBRemoteTCPLaunchTargetProvider.TYPE_ID));
					}
				}
			}

			boolean isTcpConnection = CDebugUtils.getAttribute(attributes,
					IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, false);

			if (isTcpConnection) {
				String remoteTcpHost = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_HOST,
						INVALID);
				String remoteTcpPort = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_PORT,
						INVALID);

				fCommandControl.queueCommand(fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
						remoteTcpHost, remoteTcpPort, true), new ImmediateDataRequestMonitor<MIInfo>(rm));
			} else {
				String serialDevice = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_DEV,
						INVALID);

				fCommandControl.queueCommand(
						fCommandFactory.createMITargetSelect(fCommandControl.getContext(), serialDevice, true),
						new ImmediateDataRequestMonitor<MIInfo>(rm));
			}
		} else {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Cannot reconnect to target.", //$NON-NLS-1$
					null));
			rm.done();
		}
	}

	@Override
	public void detachDebuggerFromProcess(IDMContext dmc, final RequestMonitor rm) {

		MIExitedProcessDMC exitedProc = DMContexts.getAncestorOfType(dmc, MIExitedProcessDMC.class);
		if (exitedProc != null) {
			super.detachDebuggerFromProcess(dmc, rm);
			return;
		}

		ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
		final IMIContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);

		if (controlDmc != null && containerDmc != null) {
			if (!doCanDetachDebuggerFromProcess()) {
				rm.setStatus(
						new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Detach not supported.", null)); //$NON-NLS-1$
				rm.done();
				return;
			}

			IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class);
			if (runControl != null && !runControl.isTargetAcceptingCommands()) {
				fBackend.interrupt();
			}

			// Remember that this process was detached so we don't show it as an exited process.
			// We must set this before sending the detach command to gdb to avoid race conditions
			getDetachedProcesses().add(containerDmc.getGroupId());
			fCommandControl.queueCommand(fCommandFactory.createMITargetDetach(controlDmc, containerDmc.getGroupId()),
					new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
						@Override
						protected void handleCompleted() {
							if (isSuccess()) {
								// Bug in GDB 7.2 where removing an inferior will lead to a crash when running other processes.
								// I'm hoping it will be fixed in 7.2.1
								//    			        	fCommandControl.queueCommand(
								//    			        			fCommandFactory.createMIRemoveInferior(fCommandControl.getContext(), containerDmc.getGroupId()),
								//    			    				new DataRequestMonitor<MIInfo>(getExecutor(), rm));
								rm.done();
							} else {
								// This command fails with GDB 7.2 because of a GDB bug, which was fixed with GDB 7.2.1
								// In case we get here, we assume we are using GDB 7.2 (although we should not) and we work
								// around it.
								// Also, with GDB 7.2, removing the inferior does not work because of another bug, so we just don't do it.
								fCommandControl.queueCommand(fCommandFactory.createMITargetDetach(containerDmc),
										new DataRequestMonitor<MIInfo>(getExecutor(), rm) {
											@Override
											protected void handleFailure() {
												// Detach failed
												getDetachedProcesses().remove(containerDmc.getGroupId());
												super.handleFailure();
											}
										});
							}
						}
					});
		} else {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid context.", null)); //$NON-NLS-1$
			rm.done();
		}
	}

	@Override
	protected boolean doIsDebugNewProcessSupported() {
		// Multi-process is not applicable to post-mortem sessions (core)
		// or to non-attach remote sessions.
		SessionType type = fBackend.getSessionType();

		if (type == SessionType.CORE) {
			return false;
		}

		if (type == SessionType.REMOTE && !fBackend.getIsAttachSession()) {
			return false;
		}

		// Multi-process does not work for all-stop right now
		IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class);
		if (runControl != null && runControl.getRunMode() == MIRunMode.ALL_STOP) {
			// Only one process is allowed in all-stop (for now)
			return getNumConnected() == 0;
			// NOTE: when we support multi-process in all-stop mode,
			// we will need to interrupt the target to when starting
			// the new process.
		}

		return true;
	}

	@Override
	protected Sequence getDebugNewProcessSequence(DsfExecutor executor, boolean isInitial, IDMContext dmc, String file,
			Map<String, Object> attributes, DataRequestMonitor<IDMContext> rm) {
		return new DebugNewProcessSequence_7_2(executor, isInitial, dmc, file, attributes, rm);
	}

	@Override
	public void getProcessesBeingDebugged(final IDMContext dmc, final DataRequestMonitor<IDMContext[]> rm) {
		if (getTraceVisualization()) {
			// If we are visualizing data during a live session, we should not ask GDB for the list of threads,
			// because we will get the list of active threads, while GDB only cares about thread 1 for visualization.
			final IMIContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IMIContainerDMContext.class);
			if (containerDmc != null) {
				IProcessDMContext procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class);
				rm.setData(new IMIExecutionDMContext[] { createExecutionContext(containerDmc,
						createThreadContext(procDmc, TRACE_VISUALIZATION_THREAD_ID), TRACE_VISUALIZATION_THREAD_ID) });
				rm.done();
				return;
			}
		}

		super.getProcessesBeingDebugged(dmc, rm);
	}

	/**
	 * Creates the container context that is to be used for the new process that will
	 * be created by the restart operation.
	 * This container does not have its pid yet, while the container of the process
	 * that is being restarted does have its pid.
	 * Starting with GDB 7.2, the groupId stays the same when restarting a process, so
	 * we should re-use it; this is particularly important since we support multi-process
	 * and we need the proper groupId
	 *
	 * @since 4.0
	 */
	@Override
	protected IMIContainerDMContext createContainerContextForRestart(String groupId) {
		IProcessDMContext processDmc = createProcessContext(fCommandControl.getContext(),
				MIProcesses.UNKNOWN_PROCESS_ID);
		return createContainerContext(processDmc, groupId);
	}

	@Override
	public void restart(final IContainerDMContext containerDmc, Map<String, Object> attributes,
			DataRequestMonitor<IContainerDMContext> rm) {
		fProcRestarting.add(containerDmc);
		super.restart(containerDmc, attributes, new ImmediateDataRequestMonitor<IContainerDMContext>(rm) {
			@Override
			protected void handleCompleted() {
				if (!isSuccess()) {
					fProcRestarting.remove(containerDmc);
				}
				setData(getData());
				super.handleCompleted();
			}
		});
	}

	/**
	 * @since 5.1
	 */
	@DsfServiceEventHandler
	public void eventDispatched(MIThreadGroupAddedEvent e) {
		IProcessDMContext procDmc = e.getDMContext();
		IMIContainerDMContext containerDmc = e.getGroupId() != null ? createContainerContext(procDmc, e.getGroupId())
				: null;
		getSession().dispatchEvent(new ContainerCreatedDMEvent(containerDmc), getProperties());
	}

	/** @since 4.0 */
	@DsfServiceEventHandler
	@Override
	public void eventDispatched(IExitedDMEvent e) {
		IDMContext dmc = e.getDMContext();

		if (dmc instanceof IContainerDMContext) {
			MIBreakpointsManager bpmService = getServicesTracker().getService(MIBreakpointsManager.class);

			// Time to remove the tracking of a restarting process
			boolean restarting = fProcRestarting.remove(dmc);

			if (bpmService != null) {
				if (!restarting) {
					// Process exited, remove it from the thread break point filtering
					bpmService.removeTargetFilter((IContainerDMContext) dmc);

					if (dmc instanceof IBreakpointsTargetDMContext) {
						// A process has died, we should stop tracking its breakpoints, but only if it is not restarting
						// We only do this when the process is a breakpointTargetDMC itself (GDB < 7.4);
						// we don't want to stop tracking breakpoints when breakpoints are only set once
						// for all processes (GDB >= 7.4)
						if (fBackend.getSessionType() != SessionType.CORE) {
							IBreakpointsTargetDMContext bpTargetDmc = (IBreakpointsTargetDMContext) dmc;
							bpmService.stopTrackingBreakpoints(bpTargetDmc, new ImmediateRequestMonitor() {
								@Override
								protected void handleCompleted() {
									// Ok, no need to report any error because we may have already shutdown.
									// We need to override handleCompleted to avoid risking having a error printout in the log
								}
							});
						}
					}
				}
			}
		}

		super.eventDispatched(e);
	}

	/**
	 * GDB 7.2 has a bug which causes a gdbserver crash if we set the binary after we
	 * have connected to the target.  Because GDB 7.2.1 was not released when CDT 8.0
	 * was released, we need to workaround the bug in Eclipse.
	 *
	 * This method can be overridden to easily disable the workaround, for versions
	 * of GDB that no longer have the bug.
	 *
	 * See http://sourceware.org/ml/gdb-patches/2011-03/msg00531.html
	 * and Bug 352998
	 *
	 * @since 4.1
	 */
	protected boolean needFixForGDB72Bug352998() {
		return true;
	}

	/**
	 * @since 4.1
	 */
	@DsfServiceEventHandler
	public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
		setTraceVisualization(e.isVisualizationModeEnabled());
	}

	/**
	 * @since 4.6
	 */
	@Override
	public void canDetachDebuggerFromSomeProcesses(IDMContext[] dmcs, final DataRequestMonitor<Boolean> rm) {
		canDetachFromProcesses(dmcs, false, rm);
	}

	/**
	 * @since 4.6
	 */
	@Override
	public void canDetachDebuggerFromAllProcesses(IDMContext[] dmcs, DataRequestMonitor<Boolean> rm) {
		canDetachFromProcesses(dmcs, true, rm);
	}

	/**
	 * @since 4.6
	 */
	protected void canDetachFromProcesses(IDMContext[] dmcs, boolean all, DataRequestMonitor<Boolean> rm) {
		Set<IMIContainerDMContext> contDmcs = new HashSet<>();
		for (IDMContext c : dmcs) {
			IMIContainerDMContext contDmc = DMContexts.getAncestorOfType(c, IMIContainerDMContext.class);
			if (contDmc != null) {
				contDmcs.add(contDmc);
			}
		}

		Iterator<IMIContainerDMContext> it = contDmcs.iterator();
		if (!it.hasNext()) {
			rm.setData(false);
			rm.done();
			return;
		}
		canDetachDebuggerFromProcess(it.next(), new CanDetachRequestMonitor(it, all, rm));
	}

	/**
	 * @since 4.6
	 */
	@Override
	public void detachDebuggerFromProcesses(IDMContext[] dmcs, final RequestMonitor rm) {
		Set<IMIContainerDMContext> contDmcs = new HashSet<>();
		for (IDMContext c : dmcs) {
			IMIContainerDMContext contDmc = DMContexts.getAncestorOfType(c, IMIContainerDMContext.class);
			if (contDmc != null) {
				contDmcs.add(contDmc);
			}
		}
		if (contDmcs.isEmpty()) {
			rm.done();
			return;
		}

		CountingRequestMonitor crm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), rm);
		crm.setDoneCount(contDmcs.size());
		for (IMIContainerDMContext contDmc : contDmcs) {
			detachDebuggerFromProcess(contDmc, crm);
		}
	}

	/**
	 * @since 4.6
	 */
	@Override
	public void canTerminateSome(IThreadDMContext[] dmcs, DataRequestMonitor<Boolean> rm) {
		canTerminate(dmcs, false, rm);
	}

	/**
	 * @since 4.6
	 */
	@Override
	public void canTerminateAll(IThreadDMContext[] dmcs, DataRequestMonitor<Boolean> rm) {
		canTerminate(dmcs, true, rm);
	}

	/**
	 * @since 4.6
	 */
	protected void canTerminate(IThreadDMContext[] dmcs, boolean all, DataRequestMonitor<Boolean> rm) {
		Iterator<IThreadDMContext> it = Arrays.asList(dmcs).iterator();
		if (!it.hasNext()) {
			rm.setData(false);
			rm.done();
			return;
		}
		canTerminate(it.next(), new CanTerminateRequestMonitor(it, all, rm));
	}

	/**
	 * @since 4.6
	 */
	@Override
	public void terminate(IThreadDMContext[] dmcs, RequestMonitor rm) {
		if (dmcs.length == 0) {
			rm.done();
			return;
		}

		CountingRequestMonitor crm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), rm);
		crm.setDoneCount(dmcs.length);
		for (IThreadDMContext threadDmc : dmcs) {
			terminate(threadDmc, crm);
		}
	}
}
