Skip to content

On Python 3, sock.makefile('rb').readline() doesn't handle blocking errors correctly #274

@vstinner

Description

@vstinner

On Python 3, socket.socket is monkey-patched to GreenSocket (of eventlet.greenio.base) object. When sock.makefile('rb') is called,

sock.makefile('rb') creates a SocketIO object (of socket). SocketIO.readline() calls GreenSocket.recv_into() until it gets enough data. It stops when recv_into() returns 0 byte... but also when it returns None.

GreenSocket.recv_into() starts with a trampoline to check if we have data to read, but sometimes this check is not enough: recv_into() raises a BlockingIOError. Sadly, GreenSocket.recv_into() only calls the trampoline once, it doesn't handle BlockingIOError.

In case of BlockingIOError, recv_into() is indirectly converted to None, and readline() interprets None as "end of line" so readline() returns an incomplete or empty line.

In the unit test of the OpenStack Glance project, an unit test fails because the HTTP client gets a BadStatusLine (of http.client). In fact, the underlying recv_into() raised BlockingIOError and the read is not retried.

I will propose a fix.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions