Code review comment: At the end we should also take into account whether this partition actually occupies local resources (see https://issues.apache.org/jira/browse/FLINK-12890) otherwise TM and its connection can be released independently.

Code before review:
void markFinished(Map<String, Accumulator<?, ?>> userAccumulators, IOMetrics metrics) {
assertRunningInJobMasterMainThread();
while (true) {
ExecutionState current = this.state;
if (current == RUNNING || current == DEPLOYING) {
if (transitionState(current, FINISHED)) {
try {
for (IntermediateResultPartition finishedPartition
: getVertex().finishAllBlockingPartitions()) {
IntermediateResultPartition[] allPartitions = finishedPartition
.getIntermediateResult().getPartitions();
PartitionTable<ResourceID> partitionTable = vertex.getExecutionGraph().getPartitionTable();
for (IntermediateResultPartition partition : allPartitions) {
ResultPartitionDeploymentDescriptor descriptor = producedPartitions.get(partition.getPartitionId());
if (!descriptor.isReleasedOnConsumption()) {
if (!taskManagerLocationFuture.isDone()) {
throw new IllegalStateException("Execution finished without having an assigned location.");
} else {
partitionTable.startTrackingPartition(
getAssignedResourceLocation().getResourceID(),
descriptor.getShuffleDescriptor().getResultPartitionID());
}
}
}
for (IntermediateResultPartition partition : allPartitions) {
scheduleOrUpdateConsumers(partition.getConsumers());
}
}
updateAccumulatorsAndMetrics(userAccumulators, metrics);
releaseAssignedResource(null);
vertex.getExecutionGraph().deregisterExecution(this);
}
finally {
vertex.executionFinished(this);
}
return;
}
}
else if (current == CANCELING) {
completeCancelling(userAccumulators, metrics);
return;
}
else if (current == CANCELED || current == FAILED) {
if (LOG.isDebugEnabled()) {
LOG.debug("Task FINISHED, but concurrently went to state " + state);
}
return;
}
else {
markFailed(new Exception("Vertex received FINISHED message while being in state " + state));
return;
}
}
}

Line under review: if (!descriptor.isReleasedOnConsumption()) {

Code after addressing the review:
void markFinished(Map<String, Accumulator<?, ?>> userAccumulators, IOMetrics metrics) {
assertRunningInJobMasterMainThread();
while (true) {
ExecutionState current = this.state;
if (current == RUNNING || current == DEPLOYING) {
if (transitionState(current, FINISHED)) {
try {
for (IntermediateResultPartition finishedPartition
: getVertex().finishAllBlockingPartitions()) {
IntermediateResultPartition[] allPartitions = finishedPartition
.getIntermediateResult().getPartitions();
for (IntermediateResultPartition partition : allPartitions) {
scheduleOrUpdateConsumers(partition.getConsumers());
}
}
updateAccumulatorsAndMetrics(userAccumulators, metrics);
releaseAssignedResource(null);
vertex.getExecutionGraph().deregisterExecution(this);
}
finally {
vertex.executionFinished(this);
}
return;
}
}
else if (current == CANCELING) {
completeCancelling(userAccumulators, metrics);
return;
}
else if (current == CANCELED || current == FAILED) {
if (LOG.isDebugEnabled()) {
LOG.debug("Task FINISHED, but concurrently went to state " + state);
}
return;
}
else {
markFailed(new Exception("Vertex received FINISHED message while being in state " + state));
return;
}
}
}