Skip to content

GCS, S3, ADLS: Handle EOF in inputStreams - #16055

Merged
danielcweeks merged 5 commits into
apache:mainfrom
vladislav-sidorovich:bugs/gcs-handle-eof
Jun 5, 2026
Merged

GCS, S3, ADLS: Handle EOF in inputStreams#16055
danielcweeks merged 5 commits into
apache:mainfrom
vladislav-sidorovich:bugs/gcs-handle-eof

Conversation

@vladislav-sidorovich

@vladislav-sidorovich vladislav-sidorovich commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

Returned EOF value was ignored and stale byte from singleByteBuffer was retuned in read().

In read(byte[] b, int off, int len) behavior was correct, only metrics and pos were affected.

@github-actions github-actions Bot added the GCP label Apr 19, 2026

@anoopj anoopj left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix looks accurate to me. But the same bug exists in S3 and ADLS also. It would be worth calling out in the PR description.

Comment thread gcp/src/test/java/org/apache/iceberg/gcp/gcs/TestGCSInputStream.java Outdated
@anoopj

anoopj commented Apr 20, 2026

Copy link
Copy Markdown
Member

I filed #16062 to keep track of this general problem.

@vladislav-sidorovich

Copy link
Copy Markdown
Contributor Author

I filed #16062 to keep track of this general problem.

What do you think will be better PR per cloud storage or one PR for all of them?

@vladislav-sidorovich

Copy link
Copy Markdown
Contributor Author

I filed #16062 to keep track of this general problem.

What do you think will be better PR per cloud storage or one PR for all of them?

Well, it's not a lot of code... I will add S3 and ADLS here.

@vladislav-sidorovich vladislav-sidorovich changed the title GCS: Handle EOF in GCS inputStream GCS, S3, ADLS: Handle EOF in inputStreams Apr 20, 2026
@anoopj

anoopj commented Apr 21, 2026

Copy link
Copy Markdown
Member

I've pinged @nastra @danielcweeks @amogh-jahagirdar

@amogh-jahagirdar amogh-jahagirdar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @vladislav-sidorovich and @anoopj for reviewing! This looks right to me, but I think we should also get @danielcweeks input on this as well. I'm curious if you've seen issues with EOF exceptions in practice? My guess is so far we've largely been getting lucky because we issue targeted range reads / always reading the appropriate length from metadata.

@vladislav-sidorovich

Copy link
Copy Markdown
Contributor Author

Thanks @vladislav-sidorovich and @anoopj for reviewing! This looks right to me, but I think we should also get @danielcweeks input on this as well. I'm curious if you've seen issues with EOF exceptions in practice? My guess is so far we've largely been getting lucky because we issue targeted range reads / always reading the appropriate length from metadata.

I was only reviewing GCP module to check if we have any issues and find it. I believe in PROD usage buffered reader was used, so the problems were minor metrics inaccuracies.

@steveloughran steveloughran left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these stores can return EOF if

  • you've run out of data
  • the connection is broken
  • bad stuff happening on the http channel, especially if wildfly and openssl is involved

s3afs input stream really tries to differentiate End of File and End of Network connection, as that can be retried.

@vladislav-sidorovich

Copy link
Copy Markdown
Contributor Author

Thanks @vladislav-sidorovich and @anoopj for reviewing! This looks right to me, but I think we should also get @danielcweeks input on this as well. I'm curious if you've seen issues with EOF exceptions in practice? My guess is so far we've largely been getting lucky because we issue targeted range reads / always reading the appropriate length from metadata.

I was only reviewing GCP module to check if we have any issues and find it. I believe in PROD usage buffered reader was used, so the problems were minor metrics inaccuracies.

@danielcweeks would you be able to take a look on the PR?

@github-actions

Copy link
Copy Markdown

This pull request has been marked as stale due to 30 days of inactivity. It will be closed in 1 week if no further activity occurs. If you think that’s incorrect or this pull request requires a review, please simply write any comment. If closed, you can revive the PR at any time and @mention a reviewer or discuss it on the dev@iceberg.apache.org list. Thank you for your contributions.

@github-actions github-actions Bot added the stale label May 27, 2026
@steveloughran

Copy link
Copy Markdown
Contributor

should be fixed, rather than closed. important in production, as at scale these fails will happen daily

@vladislav-sidorovich

vladislav-sidorovich commented May 27, 2026

Copy link
Copy Markdown
Contributor Author

Not stale

@vladislav-sidorovich

Copy link
Copy Markdown
Contributor Author

Thanks @vladislav-sidorovich and @anoopj for reviewing! This looks right to me, but I think we should also get @danielcweeks input on this as well. I'm curious if you've seen issues with EOF exceptions in practice? My guess is so far we've largely been getting lucky because we issue targeted range reads / always reading the appropriate length from metadata.

I was only reviewing GCP module to check if we have any issues and find it. I believe in PROD usage buffered reader was used, so the problems were minor metrics inaccuracies.

@danielcweeks would you be able to take a look on the PR?

@danielcweeks would you be able to take a look on the PR?

@github-actions github-actions Bot removed the stale label May 28, 2026
@danielcweeks
danielcweeks self-requested a review June 5, 2026 23:38

@danielcweeks danielcweeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks everyone for the reviews, this looks correct to me.

@danielcweeks
danielcweeks merged commit 9bbde25 into apache:main Jun 5, 2026
36 checks passed
dbtsai added a commit to dbtsai/iceberg that referenced this pull request Jul 16, 2026
…tStreamWrapper

In read(byte[], int, int), readOperations was incremented unconditionally,
including on EOF (bytesRead == -1), contradicting the read() method above it
and the EOF-handling convention from apache#16055. Guard both counters on != -1 so
an EOF read counts neither bytes nor an operation.

Co-authored-by: Isaac
dbtsai added a commit to dbtsai/iceberg that referenced this pull request Jul 18, 2026
Review feedback on the read-metrics instrumentation:
- AnalyticsCoreUtil.readVectored: count range.length() synchronously on the
  caller thread instead of in the range-future completion callback. The futures
  complete on analytics-core background threads; under HadoopMetricsContext,
  READ_BYTES accumulates per-thread and Spark reads task input from the task
  thread, so callback counting would land the bytes on the wrong thread and
  never reach Spark's task metrics (viirya).
- readTail on S3/GCS/ADLS: guard readOperations together with readBytes on
  bytesRead > 0 so an empty-tail read counts neither (szehon-ho).
- AnalyticsCoreUtil.read()/read(byte[],int,int): guard both counters on
  bytesRead != -1 for consistency with the rest of the PR and apache#16055 (JoshRosen).
- TestS3InputStream: drop the shared lenient() getObject stub and stub inline
  in the two tests that need it, restoring strict stubbing (szehon-ho).

A codebase-wide scan for the same pattern found two more streams with the same
bug (both pre-existing): Aliyun OSSInputStream and Dell EcsSeekableInputStream
incremented read metrics unconditionally, so an EOF read over-counted an
operation and, in the buffered path, readBytes.increment(-1) decremented the
byte counter and corrupted pos. Both now read first and return early on EOF
before touching pos/counters.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants