Skip to content

Assertion failure with vsock: assert(readResult == .some) in BaseSocketChannel.swift #3500

@aduermael

Description

@aduermael

Description

When using SwiftNIO with vsock (virtual sockets) through Apple's Containerization framework, the assertion assert(readResult == .some) in BaseSocketChannel.swift (around line 1203) fails intermittently during container startup.

The crash occurs in NIO Event Loop Threads (NIO-ELT-*) with a stack trace pointing to:

NIOPosix/BaseSocketChannel.swift:1203: Assertion failed

Root Cause Analysis

The assertion assumes that kqueue (macOS) and epoll (Linux) provide implicit synchronization - that a POLLIN notification will only be delivered when data is actually available to read. However, vsock (virtio-vsock) does not appear to have the same guarantees.

vsock communication goes through a hypervisor layer (in this case, Apple's Virtualization framework via VZVirtualMachineManager), which may introduce timing differences that cause spurious read notifications - similar to io_uring behavior.

Precedent: io_uring

This assertion is already conditionally disabled for io_uring:

#if !SWIFTNIO_USE_IO_URING
assert(readResult == .some)
#endif

The comment in the code explains that io_uring "lacks implicit synchronization between poll mask modifications and returned events." vsock appears to have the same characteristic when used through a hypervisor.

Reference: 8ea0afb

Proposed Fix

Handle .none gracefully instead of asserting, similar to how io_uring handles this case:

// Instead of:
#if !SWIFTNIO_USE_IO_URING
assert(readResult == .some)
#endif

// Consider:
if readResult == .none {
    // Spurious wakeup - no data available despite POLLIN
    // This can happen with vsock or other non-standard socket types
    self.readIfNeeded0()
    return .none
}

Environment

Reproduction

The issue occurs when:

  1. Using Apple's Containerization framework to create Linux containers
  2. The framework establishes vsock connections for host-guest communication
  3. During container startup, spurious POLLIN notifications trigger the assertion

I'll also file a related issue on apple/containerization to cross-reference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions