socket_connect_fix

Version, currently 0.1.02 versions

github.com/nogginly/socket_connect_fix.cr

Makes Socket#connect report connection failures that the kernel defers to SO_ERROR (e.g. ECONNREFUSED on macOS), so Crystal's multi-address fallback works and refused connections raise Socket::ConnectError.

0 stars
0 dependents
License: MIT

Nothing has been indexed for 0.1.0 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.

Installation

# Add this to your shard.yml
dependencies:
  socket_connect_fix:
    github: nogginly/socket_connect_fix.cr
    version: ~> 0.1.0

Then run:

shards install

shard.yml

No shard.yml has been indexed for 0.1.0. You can read it on the repository.

Dependencies

Unknown: the shard.yml for this version has not been read yet.

README

This README is the one indexed from the repository at its latest ref, not from the tag for this version.

socket_connect_fix

On macOS (and possibly other BSD-derived systems), Crystal's Socket#connect can report a refused connection as successful. The refusal is only visible in the kernel's SO_ERROR, which Crystal does not read. Consequences:

  • TCPSocket.new("localhost", port) stops at ::1 and never tries 127.0.0.1, so servers listening only on IPv4 (e.g. Ollama) appear unreachable.
  • Any refused connection returns a dead socket that fails later with a misleading error such as getpeername: Invalid argument.

This shard checks SO_ERROR after connect and reports failures as Socket::ConnectError, so Crystal's existing address fallback works.

Installation

dependencies:
  socket_connect_fix:
    github: nogginly/socket_connect_fix.cr

Usage

require "socket_connect_fix"

Require it once, anywhere in the application. The change applies to every socket in the program, including those opened by HTTP::Client and database drivers. Libraries should not require it; applications opt in.

Compatibility

CI runs the specs with Crystal 1.20 and the latest release on Linux and macOS, and 1.20 on Windows. The fix applies on Unix only; it is a no-op on Windows. It redefines Socket#connect(addr, timeout, &) and relies on that signature. Re-run the specs when upgrading Crystal, and remove the shard once the upstream fix ships.

Development

crystal spec
crystal spec -Devloop=libevent
crystal spec -Dsocket_connect_fix_disabled   # on macOS, closed-port specs should fail

Contributions, by invitation!

With apologies, at this time contributions to this project are by invitation only and limited to people I know and see often.

  • These are early days for the project and I am busy with family and work.
  • At this time I want to work on this at a manageable pace.