Search before asking
I searched titles, bodies, and comments for HadoopDataInputStream, skipFully, seek past EOF, HDFS seek hang, Hadoop skip EOF, and related filesystem terms. I also inspected the open Hadoop dependency-alignment PR #3699; it does not touch this code path.
Fluss version
main (development) at 31621117db9b21e8e00a6e716b3a13b7b66e18be
- The same implementation is present in
v0.9.1-incubating, v0.9.0-incubating, and v0.8.0-incubating
Please describe the bug 🐞
HadoopDataInputStream.seek(long) optimizes small forward seeks by calling skipFully(delta). If the requested position is past EOF, the underlying InputStream.skip(long) returns 0. The loop in skipFully then makes no progress and spins forever:
|
public void skipFully(long bytes) throws IOException { |
|
while (bytes > 0) { |
|
bytes -= fsDataInputStream.skip(bytes); |
|
} |
This contradicts the public FSDataInputStream.seek contract, which says callers cannot seek past the end of the stream and reports seek errors through IOException:
|
/** |
|
* Seek to the given offset from the start of the file. The next read() will be from that |
|
* location. Can't seek past the end of the stream. |
|
* |
|
* @param desired the desired offset |
|
* @throws IOException Thrown if an error occurred while seeking inside the input stream. |
|
*/ |
|
public abstract void seek(long desired) throws IOException; |
Java's InputStream.skip contract permits returning fewer bytes than requested, including 0.
Reproduction
The existing SeekableByteArrayInputStream test fixture already returns 0 from skip at EOF. Adding this focused case to HadoopDataInputStreamTest reproduces the hang:
@Test
void testSeekPastEndOfStream() {
FSDataInputStream input =
new FSDataInputStream(new SeekableByteArrayInputStream(new byte[1]));
HadoopDataInputStream stream = new HadoopDataInputStream(input);
assertThatThrownBy(() -> stream.seek(2)).isInstanceOf(EOFException.class);
}
Run it with:
./mvnw -pl fluss-filesystems/fluss-fs-hadoop -am \
-Dtest=HadoopDataInputStreamTest \
-Dsurefire.failIfNoSpecifiedTests=false test
I also reproduced this twice against Hadoop's real local filesystem implementation using a one-byte file and seek(2). Both runs timed out after two seconds:
before seek target=2 length=1
TIMEOUT after 2s (seek did not return)
The nearby control seek(1) returned normally with position 1.
Expected behavior
The call should promptly throw IOException/EOFException because the requested position is past EOF.
Actual behavior
seek(2) never returns. The thread remains in the skipFully loop.
No special configuration or external service is required.
Solution
Delegate skipFully to Hadoop's existing org.apache.hadoop.io.IOUtils.skipFully(InputStream, long), or implement the same zero-progress handling: when skip returns 0, read one byte and throw EOFException if EOF has been reached.
A regression test can be added to the existing HadoopDataInputStreamTest. This should require no new dependency and no API or storage-format change.
Are you willing to submit a PR?
Search before asking
I searched titles, bodies, and comments for
HadoopDataInputStream,skipFully,seek past EOF,HDFS seek hang,Hadoop skip EOF, and related filesystem terms. I also inspected the open Hadoop dependency-alignment PR #3699; it does not touch this code path.Fluss version
main (development)at31621117db9b21e8e00a6e716b3a13b7b66e18bev0.9.1-incubating,v0.9.0-incubating, andv0.8.0-incubatingPlease describe the bug 🐞
HadoopDataInputStream.seek(long)optimizes small forward seeks by callingskipFully(delta). If the requested position is past EOF, the underlyingInputStream.skip(long)returns0. The loop inskipFullythen makes no progress and spins forever:fluss/fluss-filesystems/fluss-fs-hadoop/src/main/java/org/apache/fluss/fs/hdfs/HadoopDataInputStream.java
Lines 132 to 135 in 3162111
This contradicts the public
FSDataInputStream.seekcontract, which says callers cannot seek past the end of the stream and reports seek errors throughIOException:fluss/fluss-common/src/main/java/org/apache/fluss/fs/FSDataInputStream.java
Lines 36 to 43 in 3162111
Java's
InputStream.skipcontract permits returning fewer bytes than requested, including0.Reproduction
The existing
SeekableByteArrayInputStreamtest fixture already returns0fromskipat EOF. Adding this focused case toHadoopDataInputStreamTestreproduces the hang:Run it with:
./mvnw -pl fluss-filesystems/fluss-fs-hadoop -am \ -Dtest=HadoopDataInputStreamTest \ -Dsurefire.failIfNoSpecifiedTests=false testI also reproduced this twice against Hadoop's real local filesystem implementation using a one-byte file and
seek(2). Both runs timed out after two seconds:The nearby control
seek(1)returned normally with position1.Expected behavior
The call should promptly throw
IOException/EOFExceptionbecause the requested position is past EOF.Actual behavior
seek(2)never returns. The thread remains in theskipFullyloop.No special configuration or external service is required.
Solution
Delegate
skipFullyto Hadoop's existingorg.apache.hadoop.io.IOUtils.skipFully(InputStream, long), or implement the same zero-progress handling: whenskipreturns0, read one byte and throwEOFExceptionif EOF has been reached.A regression test can be added to the existing
HadoopDataInputStreamTest. This should require no new dependency and no API or storage-format change.Are you willing to submit a PR?