-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
Corrupt .pyc files stay on disk after failed writes #126606
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
Comments
can reproduce this on cpython 3.11, git head, and on pypy (I tried on ubuntu). the problem is likely in importlib somewhere. |
the problem is def _write_atomic(path, data, mode=0o666):
"""Best-effort function to write data to a path atomically.
Be prepared to handle a FileExistsError if concurrent writing of the
temporary file is attempted."""
import os as _os
import _io
# id() is used to generate a pseudo-random filename.
path_tmp = '{}.{}'.format(path, id(path))
fd = _os.open(path_tmp,
_os.O_EXCL | _os.O_CREAT | _os.O_WRONLY, mode & 0o666)
try:
# We first write data to a temporary file, and then use os.replace() to
# perform an atomic rename.
with _io.FileIO(fd, 'wb') as file:
file.write(data)
_os.replace(path_tmp, path)
except OSError:
try:
_os.unlink(path_tmp)
except OSError:
pass
raise So we should check the result of the write call, and if the length is not equal to that of data, abort the operation. the use of
|
Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
(cherry picked from commit c695e37) Co-authored-by: CF Bolz-Tereick <[email protected]> Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
(cherry picked from commit c695e37) Co-authored-by: CF Bolz-Tereick <[email protected]> Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
…6809) GH-126606: don't write incomplete pyc files (GH-126627) (cherry picked from commit c695e37) Co-authored-by: CF Bolz-Tereick <[email protected]> Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
…6810) GH-126606: don't write incomplete pyc files (GH-126627) (cherry picked from commit c695e37) Co-authored-by: CF Bolz-Tereick <[email protected]> Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
Thanks, everyone! This is now fixed in 3.12 to |
@brettcannon thanks a lot Brett! will backport to pypy now. |
original commit message: GH-126606: don't write incomplete pyc files (GH-126627) Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
Co-authored-by: Kirill Podoprigora <[email protected]> Co-authored-by: Brett Cannon <[email protected]>
Bug report
Bug description:
If writing a
.pyc
file fails (in my case due to a file size limit imposed byulimit
), it can leave corrupt data sitting on disk. This causes a crash the second time you run the program, when the interpreter tries to load the corrupt.pyc
file instead of the original.py
file:This was a very hard bug to track down, and it seems like there's a chance to catch this and handle it gracefully. If I do a too-large write myself, I get an
OSError: [Errno 27] File too large
, and I'd imagine the interpreter can see something similar. Ideally (in my opinion - feedback appreciated!), the interpreter would notice this and then:sys.dont_write_bytecode = True
(this is the workaround I've been using).Here's the code I've been using to test this (
bigfile
can be pretty much anything, but it does seem to have to be part of a module before the interpreter will write a.pyc
file for it).Tested in Python 3.10 on OSX and Python 3.12 in an Ubuntu 24 container.
CPython versions tested on:
3.10, 3.12
Operating systems tested on:
Linux, macOS
Linked PRs
The text was updated successfully, but these errors were encountered: