Skip to content

Commit e11b7af

Browse files
committed
Ensure that file is released back to pool when seek fails
Closes gh-9370
1 parent a9fc18b commit e11b7af

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/data/RandomAccessDataFile.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -170,11 +170,11 @@ public int doRead(byte[] b, int off, int len) throws IOException {
170170
return -1;
171171
}
172172
RandomAccessFile file = this.file;
173-
if (file == null) {
174-
file = RandomAccessDataFile.this.filePool.acquire();
175-
file.seek(RandomAccessDataFile.this.offset + this.position);
176-
}
177173
try {
174+
if (file == null) {
175+
file = RandomAccessDataFile.this.filePool.acquire();
176+
file.seek(RandomAccessDataFile.this.offset + this.position);
177+
}
178178
if (b == null) {
179179
int rtn = file.read();
180180
moveOn(rtn == -1 ? 0 : 1);
@@ -185,7 +185,7 @@ public int doRead(byte[] b, int off, int len) throws IOException {
185185
}
186186
}
187187
finally {
188-
if (this.file == null) {
188+
if (this.file == null && file != null) {
189189
RandomAccessDataFile.this.filePool.release(file);
190190
}
191191
}
@@ -229,7 +229,7 @@ private long moveOn(int amount) {
229229
* Manage a pool that can be used to perform concurrent reads on the underlying
230230
* {@link RandomAccessFile}.
231231
*/
232-
private class FilePool {
232+
class FilePool {
233233

234234
private final int size;
235235

spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/data/RandomAccessDataFileTests.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
import java.io.File;
2020
import java.io.FileOutputStream;
21+
import java.io.IOException;
2122
import java.io.InputStream;
23+
import java.io.RandomAccessFile;
2224
import java.lang.reflect.Field;
2325
import java.util.ArrayList;
2426
import java.util.Arrays;
@@ -35,10 +37,20 @@
3537
import org.junit.Test;
3638
import org.junit.rules.ExpectedException;
3739
import org.junit.rules.TemporaryFolder;
40+
import org.mockito.internal.util.MockUtil;
41+
import org.mockito.invocation.InvocationOnMock;
42+
import org.mockito.stubbing.Answer;
3843

3944
import org.springframework.boot.loader.data.RandomAccessData.ResourceAccess;
45+
import org.springframework.boot.loader.data.RandomAccessDataFile.FilePool;
46+
import org.springframework.test.util.ReflectionTestUtils;
4047

4148
import static org.assertj.core.api.Assertions.assertThat;
49+
import static org.junit.Assert.fail;
50+
import static org.mockito.BDDMockito.willAnswer;
51+
import static org.mockito.BDDMockito.willThrow;
52+
import static org.mockito.Matchers.anyLong;
53+
import static org.mockito.Mockito.spy;
4254

4355
/**
4456
* Tests for {@link RandomAccessDataFile}.
@@ -309,4 +321,38 @@ public void close() throws Exception {
309321
assertThat(queue.size()).isEqualTo(0);
310322
}
311323

324+
@Test
325+
public void seekFailuresDoNotPreventSubsequentReads() throws Exception {
326+
FilePool filePool = (FilePool) ReflectionTestUtils.getField(this.file,
327+
"filePool");
328+
FilePool spiedPool = spy(filePool);
329+
ReflectionTestUtils.setField(this.file, "filePool", spiedPool);
330+
willAnswer(new Answer<RandomAccessFile>() {
331+
332+
@Override
333+
public RandomAccessFile answer(InvocationOnMock invocation) throws Throwable {
334+
RandomAccessFile originalFile = (RandomAccessFile) invocation
335+
.callRealMethod();
336+
if (new MockUtil().isSpy(originalFile)) {
337+
return originalFile;
338+
}
339+
RandomAccessFile spiedFile = spy(originalFile);
340+
willThrow(new IOException("Seek failed")).given(spiedFile)
341+
.seek(anyLong());
342+
return spiedFile;
343+
}
344+
345+
}).given(spiedPool).acquire();
346+
347+
for (int i = 0; i < 5; i++) {
348+
try {
349+
this.file.getInputStream(ResourceAccess.PER_READ).read();
350+
fail("Read should fail due to exception from seek");
351+
}
352+
catch (IOException ex) {
353+
354+
}
355+
}
356+
}
357+
312358
}

0 commit comments

Comments
 (0)