Gen Luo created FLINK-24965:
-------------------------------

             Summary: Improper usage of Map.Entry after Entry Iterator.remove 
in TaskLocaStateStoreImpl#pruneCheckpoints
                 Key: FLINK-24965
                 URL: https://issues.apache.org/jira/browse/FLINK-24965
             Project: Flink
          Issue Type: Bug
          Components: Runtime / State Backends
            Reporter: Gen Luo


In TaskLocaStateStoreImpl#pruneCheckpoints, a list is created to store 
snapshots which should be removed, and entries to remove are directly add into 
the list. The code is like this.
{code:java}
Iterator<Map.Entry<Long, TaskStateSnapshot>> entryIterator =
        storedTaskStateByCheckpointID.entrySet().iterator();

while (entryIterator.hasNext()) {
    Map.Entry<Long, TaskStateSnapshot> snapshotEntry = entryIterator.next();
    long entryCheckpointId = snapshotEntry.getKey();
    if (pruningChecker.test(entryCheckpointId)) {
        toRemove.add(snapshotEntry);
        entryIterator.remove();
    } else if (breakOnceCheckerFalse) {
        break;
    }
} {code}
 

 

However, according to the javadoc of Map.Entry,
{code:java}
the behavior of a map entry is undefined if the backing map has been modified 
after the entry was returned by the iterator, except through the setValue 
operation on the map entry. {code}
 entries should not be reserved for further usage after iterator.remove is 
called. In this case, where the map is a TreeMap, if the first entry is skipped 
and removal happens from the second element in `storedTaskStateByCheckpointID`, 
 entries return by entryIterator.next will be the same object and the list will 
be filled with it.

 

A possible fix is to use `new AbstractMap.SimpleEntry<>(snapshotEntry.getKey(), 
snapshotEntry.getValue())` instead of snapshotEntry itself to add into the list.

 

The issue is a minor one since all usage of this method seems safe so far.



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to