-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: bytes: make Reader.WriteTo side effect free when the Reader is empty #52382
Comments
I'm not sure I understand all the details here. However, in general, I suppose that it does little harm to call It seems to me that the code that is making concurrent calls to |
I agree, however that what Here is what the patch would be (tests aside): func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
- r.prevRune = -1
if r.i >= int64(len(r.s)) {
return 0, nil
}
+ r.prevRune = -1 To follow what func (r *Reader) Read(b []byte) (n int, err error) {
if r.i >= int64(len(r.s)) {
return 0, io.EOF
}
r.prevRune = -1 don't think we can break |
My opinion is |
I agree with that statement. |
I think it would be OK to change |
Closing this then. |
{bytes,strings}.Reader already has a few special cases making things concurrently safe. Read is one of those. |
Change https://go.dev/cl/401414 mentions this issue: |
Motivations
I recently got bitten because some code was doing concurrent
io.Copy
from shared emptybytes.Reader
.This code was safe because the
bytes.Reader.WriteTo
function was hidden in aio.NopCloser
, soio.Copy
was usingbytes.Reader.Read
, however adding support ofio.WriterTo
toio.NopCloser
had the side effect of no longer hiddingbytes.Reader.WriteTo
which trigger a race inio.Copy
.Underlying issue
The underlying issue is that
bytes.Reader.Read
andbytes.Reader.WriteTo
have different side effects when called with an empty reader.bytes.Reader.WriteTo
invalidate the previously returned rune when the reader is empty.bytes.Reader.Reader
invalidate the previously returned rune only when the reader is not empty.My understanding is that there is a weak contract about implementing
io.WriterTo
on objects also implementingio.Reader
.Is that implementation details aside (like zero copying), the side effects should be behaviorally equivalent between doing
io.ReadAll(r)
andr.WriteTo(io.Discard)
, and this weak contract is the reasonio.Copy
is allowed to attempt to useio.WriterTo
when available.However
bytes.Reader
doesn't do that.Proposal
In
bytes.Reader.WriteTo
only invalidate the previously red rune if the buffer is not empty.In code:
Note that this behaviour is currently what we have with
r.Read
Objective
This would harmonize side effects between
bytes.Reader.Read
andbytes.Reader.WriteTo
when the Reader is empty and allows for concurrentbytes.Reader.WriteTo
call with empty buffers.The text was updated successfully, but these errors were encountered: