As other solutions did not work, I implemented some custom solution.
When the processor discovers no more data shall be processed it sets a flag in the stepContext's transientUserData. To prevent the current data from getting written, it also returns null. On the next loop iteration the reader checks transientUserData flag and - if set - returns null. This makes the partition stop.
As I want to use generic readers I implemented an ItemReaderListener that performs the check and action in the afterRead() method.