Skip to content

Commit 4c9b50d

Browse files
authored
Clean up on exception while chunking XContent (#92024)
If serializing a chunk throws an exception, we must clean up the chunk before propagating the exception.
1 parent 2b472c9 commit 4c9b50d

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

docs/changelog/92024.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 92024
2+
summary: Clean up on exception while chunking XContent
3+
area: Network
4+
type: bug
5+
issues: []

server/src/main/java/org/elasticsearch/rest/ChunkedRestResponseBody.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.common.recycler.Recycler;
1515
import org.elasticsearch.common.xcontent.ChunkedToXContent;
1616
import org.elasticsearch.core.IOUtils;
17+
import org.elasticsearch.core.Releasables;
1718
import org.elasticsearch.core.Streams;
1819
import org.elasticsearch.xcontent.ToXContent;
1920
import org.elasticsearch.xcontent.XContentBuilder;
@@ -92,20 +93,32 @@ public boolean isDone() {
9293

9394
@Override
9495
public ReleasableBytesReference encodeChunk(int sizeHint, Recycler<BytesRef> recycler) throws IOException {
95-
final RecyclerBytesStreamOutput chunkStream = new RecyclerBytesStreamOutput(recycler);
96-
assert this.target == null;
97-
this.target = chunkStream;
98-
while (serialization.hasNext()) {
99-
serialization.next().toXContent(builder, params);
100-
if (chunkStream.size() >= sizeHint) {
101-
break;
96+
try {
97+
final RecyclerBytesStreamOutput chunkStream = new RecyclerBytesStreamOutput(recycler);
98+
assert target == null;
99+
target = chunkStream;
100+
while (serialization.hasNext()) {
101+
serialization.next().toXContent(builder, params);
102+
if (chunkStream.size() >= sizeHint) {
103+
break;
104+
}
105+
}
106+
if (serialization.hasNext() == false) {
107+
builder.close();
108+
}
109+
final var result = new ReleasableBytesReference(
110+
chunkStream.bytes(),
111+
() -> Releasables.closeExpectNoException(chunkStream)
112+
);
113+
target = null;
114+
return result;
115+
} finally {
116+
if (target != null) {
117+
assert false : "failure encoding chunk";
118+
IOUtils.closeWhileHandlingException(target);
119+
target = null;
102120
}
103121
}
104-
if (serialization.hasNext() == false) {
105-
builder.close();
106-
}
107-
this.target = null;
108-
return new ReleasableBytesReference(chunkStream.bytes(), () -> IOUtils.closeWhileHandlingException(chunkStream));
109122
}
110123

111124
@Override

0 commit comments

Comments
 (0)