GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — gh-119506: fix `_io.TextIOWrapper.write()` write during flush by chgnrdv · Pull Request #119507 · python/cpython Conversation
|
|
Thank you. The patch looks good to me. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Now it crashes if any of these calls fails: length of Line 1735 in bf5b646
Line 1745 in bf5b646
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| if (self->pending_bytes) { | ||
| // gh-119506: call to _textiowrapper_writeflush() | ||
| // can write new data to pending_bytes | ||
| pending = self->pending_bytes; | ||
| self->pending_bytes = b; | ||
| b = pending; | ||
| } |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
why do you swap data here?
self->pending can be list
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
If you look at the test case, where flushing the stream triggers a write, it's not a threading thing, it's because of write being called recursively.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Even single thread case, it is not possble to guarantee "first called, first written."
Simple implementation is more important.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| else if (self->pending_bytes_count + bytes_len > self->chunk_size) { | ||
| PyObject *pending = self->pending_bytes; | ||
|
|
||
| if (self->pending_bytes_count + bytes_len > self->chunk_size) { |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
How about while instead of if?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
That would also need a check to make sure that bytes_len > self->chunk_size isn't true.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
This PR seems to be addressing a similar issue as #119107 but I don't think that this PR fixes the race condition present when multi-threaded writes happen. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
After fixing my original test case, I think that this minimal patch addresses the issue in practical terms: there is still an issue where since there isn't a lock AFAIK, another thread could modify but that doesn't seem to be an issue in practice. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
I should note that there's a similar race condition issue in That's a bit more scary, given that there's an entire list iteration between that |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Note that default Python build with GIL doesn't have such race.
Other thread may call TextIOWrapper.write(b) and it appends b to self->pending_bytes. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Ah, that makes sense. Thank you for explaining! |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…ythonGH-119507) (cherry picked from commit 52586f9) Co-authored-by: Radislav Chugunov <[email protected]> Co-authored-by: Inada Naoki <[email protected]>
|
GH-119964 is a backport of this pull request to the 3.13 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…ythonGH-119507) (cherry picked from commit 52586f9) Co-authored-by: Radislav Chugunov <[email protected]> Co-authored-by: Inada Naoki <[email protected]>
|
GH-119965 is a backport of this pull request to the 3.12 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…ython#119507) Co-authored-by: Inada Naoki <[email protected]>
|
Thanks for bringing this home! Does this qualify as a security issue? I'm wondering if it will be backported to 3.10. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| } | ||
| // Since Python 3.12, allocating GC object won't trigger GC and release | ||
| // GIL. See https://github.com/python/cpython/issues/97922 | ||
| assert(!PyList_CheckExact(self->pending_bytes)); |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
I am not sure about this patch will be backported to security branches.
If it will, this line needs additional fixes. So backport is not simple.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…ython#119507) Co-authored-by: Inada Naoki <[email protected]>
|
GH-120314 is a backport of this pull request to the 3.11 branch. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
…H-119507) (#119964) gh-119506: fix `_io.TextIOWrapper.write()` write during flush (GH-119507) (cherry picked from commit 52586f9) Co-authored-by: Radislav Chugunov <[email protected]> Co-authored-by: Inada Naoki <[email protected]>
…H-119507) (#119965) gh-119506: fix `_io.TextIOWrapper.write()` write during flush (GH-119507) (cherry picked from commit 52586f9) Co-authored-by: Radislav Chugunov <[email protected]> Co-authored-by: Inada Naoki <[email protected]>
…ython#119507) Co-authored-by: Inada Naoki <[email protected]>
…119507) (#120314) Co-authored-by: Hugo van Kemenade <[email protected]> fix _io.TextIOWrapper.write() write during flush (#119507)
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
_io.TextIOWrapper.write: write during flush causes pending_bytes length mismatch
There was an error while loading. Please reload this page.