Skip to content

sendfile for sockets neglects pseudo files on Linux #93300

Closed as not planned
Closed as not planned
@illia-v

Description

@illia-v

Bug report

socket.socket.sendfile and asyncio.base_events.BaseEventLoop.sock_sendfile rely on st_size to determine an amount of bytes to be sent if count is not provided.

But st_size is equal to zero for pseudo files like /proc/cpuinfo on Linux. Therefore, the methods send no data for such files.

Related code

cpython/Lib/socket.py

Lines 355 to 360 in a637c09

try:
fsize = os.fstat(fileno).st_size
except OSError as err:
raise _GiveupOnSendfile(err) # not a regular file
if not fsize:
return 0 # empty file

try:
fsize = os.fstat(fileno).st_size
except OSError:
raise exceptions.SendfileNotAvailableError("not a regular file")
blocksize = count if count else fsize
if not blocksize:
return 0 # empty file

Example

Assuming nc -lkU some.sock and ./python -m asyncio run in the same directory:

>>> import asyncio
>>> import socket
>>> sock = socket.socket(socket.AF_UNIX)
>>> loop = asyncio.get_running_loop()
>>> await loop.sock_connect(sock, "./some.sock")
>>> with open("/proc/cpuinfo", "rb") as cpuinfo_file:
...     os.fstat(cpuinfo_file.fileno()).st_size
...     await loop.sock_sendfile(sock, cpuinfo_file)
...     sock.sendfile(cpuinfo_file)
...     len(cpuinfo_file.read())
... 
0
0
0
18294

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions