@Override
	public void run(TaskMonitor monitor) {
		TaskUtilities.addTrackedTask(this, monitor);
		taskMonitor = monitor;
		int id;
		try {
			id = obj.startTransaction(cmd.getName(), this);
		}
		catch (Throwable t) {
			Msg.error(this, "Transaction error", t);
			monitor.cancel();
			synchronized (taskMgr) {
				doneQueueProcessing = true;
				taskMgr.clearTasks(obj);
				taskMgr.taskFailed(obj, cmd, monitor);
			}
			TaskUtilities.removeTrackedTask(this);
			return;
		}
		finally {
			synchronized (taskMgr) {
				// Allow waiting task manager to continue once we have started the transaction
				taskMgr.notifyAll();
			}
		}

		boolean success = false;
		boolean commit = true;
		try {
			success = cmd.applyTo(obj, monitor);
			if (success) {
				taskMgr.taskCompleted(obj, this, monitor);
			}
		}
		catch (Throwable t) {
			synchronized (taskMgr) {
				doneQueueProcessing = true;
				taskMgr.clearQueuedCommands(obj);
			}

			if (t instanceof DomainObjectException) {
				t = t.getCause();
			}

			commit = shouldKeepData(t);

			if (isUnrecoverableException(t)) {
				monitor.cancel();
				taskMgr.clearTasks(obj);
			}
			else if (!(t instanceof RollbackException)) {
				String message =
					"An unexpected error occurred while processing the command: " + cmd.getName();
				Msg.showError(this, null, "Command Failure", message, t);
			}
		}
		finally {
			TaskUtilities.removeTrackedTask(this);
			try {
				obj.endTransaction(id, commit);
			}
			catch (DomainObjectException e) {
				Throwable cause = e.getCause();
				if (commit && !(cause instanceof ClosedException)) {
					Msg.error(this, "Transaction error", cause);
					success = false;
				}
			}
		}

		if (!success) {
			taskMgr.taskFailed(obj, cmd, monitor);
		}
	}
Returns command associated with this task

@return background command
Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/mgr/BackgroundCommandTask.java