bpo-42606: Support POSIX atomicity guarantee of O_APPEND on Windows #23712
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.


On POSIX-conforming systems, O_APPEND flag for open() must ensure
that no intervening file modification occurs between changing the file
offset and the write operation[1]. In effect, two processes that
independently opened the same file with O_APPEND can't overwrite
each other's data. On Windows, however, the Microsoft C runtime
implements O_APPEND as an lseek(fd, 0, SEEK_END) followed by write(),
which obviously doesn't provide the above guarantee. This affects
both os.open() and the builtin open() Python functions, which rely on
_wopen() from MSVCRT.
One way to achieve the desired behavior is to ensure that the Windows
handle backing the MSVCRT file descriptor has FILE_APPEND_DATA access
right, but doesn't have FILE_WRITE_DATA. This makes the Windows kernel
enforce the described semantics.
To avoid full reimplementation of _wopen(), implement the above by
duplicating the MSVCRT-created handle with fixed up access rights and
wrapping it with a new file descriptor. Note that handles created by
functions like os.dup() will still have the correct access rights (and
thus atomic behavior) because MSVCRT duplicates them with
DUPLICATE_SAME_ACCESS flag.
[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html
https://bugs.python.org/issue42606