Skip to content

bpo-17852: Maintain a list of BufferedWriter objects. Flush them on exit. #3372

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

Merged
merged 6 commits into from
Sep 22, 2017

Conversation

nascheme
Copy link
Member

@nascheme nascheme commented Sep 6, 2017

This is a fixed (hopefully) version of my previous patch. Checking buf->ok and buf->finalizing is necessary, as suggested by Antoine Pitrou.

https://bugs.python.org/issue17852

In Python 3, the buffer and the underlying file object are separate
and so the order in which objects are finalized matters.  This is
unlike Python 2 where the file and buffer were a single object and
finalization was done for both at the same time.  In Python 3, if
the file is finalized and closed before the buffer then the data in
the buffer is lost.

This change adds a doubly linked list of open file buffers.  An atexit
hook ensures they are flushed before proceeding with interpreter
shutdown.  This is addition does not remove the need to properly close
files as there are other reasons why buffered data could get lost during
finalization.

Initial patch by Armin Rigo.
The previous implementation was not careful enough to avoid
causing issues in multi-threaded cases.  Check for buf->ok
and buf->finalizing before actually doing the flush.  Also,
increase the refcnt to ensure the object does not disappear.
@nascheme nascheme merged commit 0a1ff24 into python:master Sep 22, 2017
@pitrou
Copy link
Member

pitrou commented Dec 12, 2017

Sorry for not having caught this while reviewing, but the change here doesn't work. The problem is that _Py_PyAtexit doesn't add a new callback, it replaces a single callback entry. This means that as soon as you import atexit, the IO-flushing callback gets overwritten.

nascheme added a commit to nascheme/cpython that referenced this pull request Dec 13, 2017
We can't use _Py_PyAtExit() as it only supports registering a single
callback.  It is used by the atexit module and so we can't use it.  We
can't use Py_AtExit() either because it calls functions too late in the
interpreter shutdown process.  Instead, create io._flush_all_buffers.
In io.py, register it with the atexit module.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants