-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
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
shutil.copyfile(): os.sendfile() fails with OverflowError on 32-bit system #82500
Comments
Error on a 32-bit buildbot worker where ssize_t maximum = 2,147,483,647 (2**31-1) bytes = ~2.0 GiB. test_largefile uses: # size of file to create (>2 GiB; 2 GiB == 2,147,483,648 bytes)
size = 2_500_000_000 x86 Gentoo Installed with X 3.x: ====================================================================== Traceback (most recent call last):
File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.installed/build/target/lib/python3.9/test/test_largefile.py", line 160, in test_it
shutil.copyfile(TESTFN, TESTFN2)
File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.installed/build/target/lib/python3.9/shutil.py", line 266, in copyfile
_fastcopy_sendfile(fsrc, fdst)
File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.installed/build/target/lib/python3.9/shutil.py", line 145, in _fastcopy_sendfile
sent = os.sendfile(outfd, infd, offset, blocksize)
OverflowError: Python int too large to convert to C ssize_t On Linux (Fedora 30), man sendfile shows me the prototype:
Extract of Lib/shutil.py:
offset = 0
while True:
try:
sent = os.sendfile(outfd, infd, offset, blocksize)
except OSError as err:
...
else:
if sent == 0:
break # EOF
offset += sent Extract of the Linux implementation of os.sendfile(): int in, out;
Py_ssize_t ret;
off_t offset;
...
Py_ssize_t count;
PyObject *offobj;
static char *keywords[] = {"out", "in",
"offset", "count", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile",
keywords, &out, &in, &offobj, &count))
return NULL;
...
if (!Py_off_t_converter(offobj, &offset))
return NULL;
with: static int
Py_off_t_converter(PyObject *arg, void *addr)
{
#ifdef HAVE_LARGEFILE_SUPPORT
*((Py_off_t *)addr) = PyLong_AsLongLong(arg);
#else
*((Py_off_t *)addr) = PyLong_AsLong(arg);
#endif
if (PyErr_Occurred())
return 0;
return 1;
} I understand that the error comes from the 4th sendfile() parameter: "count". The C code (of the Linux implementation) uses the "n" format for Py_ssize_t: Python/getargs.c calls PyLong_AsSsize_t(). On a 64-bit system, it's less likely to reach Py_ssize_t maximum value (max = 2**63-1), but it's easy to reach on a 32-bit system (max = 2**31-1). |
Oh, it's likely a regression caused by: commit 5bcc6d8
configure: checking for sendfile... yes pythoninfo: platform.libc_ver: glibc 2.29 |
Similar failure on ARMv7 Debian buster 3.x: pythoninfo: |
Looks like it worked: |
32-bit buildbots are back to green. Thanks for the fix! |
asyncio has the same issue
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs
The text was updated successfully, but these errors were encountered: