Skip to content

IpSocket::recv() EINTR retry logic is unreachable #5337

Description

@lestarch-autobot

Description

The IpSocket::recv() method in Drv/Ip/IpSocket.cpp (lines 181-223) has a loop that comments describe as "primarily for EINTR" (line 189), and post-loop code (line 220) states "If the loop completes, it means SOCKET_MAX_ITERATIONS of EINTR occurred."

However, the loop body always returns on every branch:

  • bytes_received_or_status > 0 → returns SOCK_SUCCESS
  • bytes_received_or_status == 0 → returns via handleZeroReturn()
  • bytes_received_or_status == -1:
    • EAGAIN/EWOULDBLOCK → returns SOCK_NO_DATA_AVAILABLE
    • ECONNRESET/EBADF → returns SOCK_DISCONNECTED
    • All other errors (including EINTR) → returns SOCK_READ_ERROR

Since the else clause at line 213 catches all remaining error cases (including errno == EINTR) and immediately returns SOCK_READ_ERROR, the loop can never iterate more than once. Lines 220-222 (return SOCK_INTERRUPTED_TRY_AGAIN) are dead code.

Impact

  • EINTR from signal delivery during recv() will incorrectly report SOCK_READ_ERROR instead of retrying
  • This can cause spurious disconnections on systems with active signal handling
  • The dead code at lines 220-222 is misleading for maintainers

Suggested Fix

Add an EINTR check before the catch-all else clause:

} else if (errno == EINTR) {
    continue;  // Retry on signal interruption
} else {
    req_read = 0;
    return SOCK_READ_ERROR;
}

Discovered In

Identified during code review for #5139 / PR #5336 (valgrind invalid fd fix). This is pre-existing and unrelated to those changes.

File Reference

Drv/Ip/IpSocket.cpp:189-222

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    CCB

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions