Fix race condition in PartGenerator

This commit fixes a race condition in PartGenerator, used by
DefaultPartHttpMessageReader. The condition can occur when a
completion signal comes in, and the state is changed to IdleFileState
at the same time.

Closes gh-28963
This commit is contained in:
Arjen Poutsma 2022-08-30 12:11:22 +02:00
parent 2c75eb8745
commit 4c0ece944a
1 changed files with 16 additions and 7 deletions

View File

@ -746,8 +746,15 @@ final class PartGenerator extends BaseSubscriber<MultipartParser.Token> {
@Override @Override
public void partComplete(boolean finalPart) { public void partComplete(boolean finalPart) {
this.completed = true; State state = PartGenerator.this.state.get();
this.finalPart = finalPart; // writeComplete might have changed our state to IdleFileState
if (state != this) {
state.partComplete(finalPart);
}
else {
this.completed = true;
this.finalPart = finalPart;
}
} }
public void writeBuffer(DataBuffer dataBuffer) { public void writeBuffer(DataBuffer dataBuffer) {
@ -771,14 +778,16 @@ final class PartGenerator extends BaseSubscriber<MultipartParser.Token> {
private void writeComplete() { private void writeComplete() {
IdleFileState newState = new IdleFileState(this); IdleFileState newState = new IdleFileState(this);
if (this.completed) { if (this.disposed) {
newState.partComplete(this.finalPart);
}
else if (this.disposed) {
newState.dispose(); newState.dispose();
} }
else if (changeState(this, newState)) { else if (changeState(this, newState)) {
requestToken(); if (this.completed) {
newState.partComplete(this.finalPart);
}
else {
requestToken();
}
} }
else { else {
MultipartUtils.closeChannel(this.channel); MultipartUtils.closeChannel(this.channel);