Skip to content

Conversation

@trinistr
Copy link
Contributor

@trinistr trinistr commented Nov 12, 2025

From #1016

Add support for UNIXSocket on Windows. Emulate anonymous sockets. Add
support for File.socket? and File::Stat#socket? where possible.
[Feature #19135]

  • Enable test for File.socket?
    • Move tests to the shared spec as it was supposed to be, so FileTest.socket? is actually tested.
    • Include a real test with #to_path.
  • Enable most tests in 'socket' library.

Following things are not supported so the tests are disabled:

  • #send_io, #recv_io,
  • DGRAM sockets (tests probably can be rewritten using STREAM sockets?),
  • SEQPACKET sockets (non-block stuff),
  • #getpeerid (UNIX IDs),
  • message flags (maybe some are supported, I don't know, documentation seems to be the blog post).

Socket pairs are emulated using a temporary file (ruby/ruby#6513 (comment)), so the behavior is different. Trying to create a Socket using a non-existent path raises a different error for whatever reason.


There are a couple bugs, reported as https://bugs.ruby-lang.org/issues/21702:

  • #remote_address.to_s returns 110 bytes always;
  • #recvfrom returns 2047 bytes of garbage as the remote address.

@trinistr trinistr force-pushed the 3.2-unixsocket-windows branch 7 times, most recently from f3ec3c8 to f87cf33 Compare November 21, 2025 17:06
@trinistr trinistr force-pushed the 3.2-unixsocket-windows branch 4 times, most recently from 51d1c32 to 8092a25 Compare November 21, 2025 18:36
Comment on lines 132 to 140
@path1 = SocketSpecs.socket_path
@path2 = SocketSpecs.socket_path.chop + '2'
rm_r(@path2)

@client_raw = Socket.new(:UNIX, :DGRAM)
@client_raw.bind(Socket.sockaddr_un(@path1))
@client_raw = Socket.new(:UNIX, :DGRAM)
@client_raw.bind(Socket.sockaddr_un(@path1))

@server_raw = Socket.new(:UNIX, :DGRAM)
@server_raw.bind(Socket.sockaddr_un(@path2))
@server_raw = Socket.new(:UNIX, :DGRAM)
@server_raw.bind(Socket.sockaddr_un(@path2))
Copy link
Contributor Author

@trinistr trinistr Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably should be possible to rewrite this using :STREAM sockets but just changing the type doesn't work.

@trinistr trinistr marked this pull request as ready for review November 21, 2025 18:41
else
# see https://bugs.ruby-lang.org/issues/21702
@addr.unix_path.should == @b.local_address.unix_path
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a special guard ruby_bug for such cases. It will not run a guarded test case on MRI but will on other Ruby implementations

From the contributing guide (#13669 is an id of the corresponding reported issue):

ruby_bug '#13669', ''...'3.2' do
  it "works like this" do
    # Specify the expected behavior here, not the bug
  end
end

Copy link
Contributor Author

@trinistr trinistr Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, forgot about it. Though, the guide says "If [bugfix] is not backported or not likely, use ruby_version_is instead." (I don't understand the point about backporting? It will still be some minimum version.), and in any case version to expect the fix in is unknown currently. Does this PR need to be parked until someone can get on the bug?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ruby_bug guard indicates that there is no any value for alternative Ruby implementations to follow the current CRuby's incorrect behaviour. If an issue isn't being fixed in CRuby and backported to the supported versions - this behaviour becomes a feature so alternative implementations need to implement it as well.

In this case it's definitely a bug and I suppose it will be fixed very soon.

Does this PR need to be parked until someone can get on the bug?

No.

As I wrote above the ruby_bug guard prevents running this case on CRuby so CI will be green. After fixing and backporting the guard is supposed to be removed. And the next release version (4.0) can be used temporary as a fixed Ruby version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the clarification!

data = @client.recvfrom(6)
(data in ["barfoo", ["AF_UNIX", String]]).should be_true
sock.close
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto ruby_bug

data.should == ["barfoo", ["AF_UNIX", @server.local_address.unix_path]]
sock.close
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: may be it makes sense to have separate cases for recvfrom called on a client and on a server socket.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've separated them, but can't say that it is definitely better. It's interesting that tests for recvfrom on other socket types usually just ignore the address part, so who knows what lurks there.

end

platform_is :linux do
# It isn't clear which platforms support remote addresses here, so only Linux tests this.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's OK to remove the guard. If it passes on CRuby CI then it's completely fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't pass, as at least OSX does not implement this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. It may be better to specify it explicitly with platform_is_not :windows, :darwin (as far as CRuby's CI uses only Linux, macOS and Windows). If specs are run on other platforms I suppose mainterners of Ruby package will let us know that there are failing tests.

# The second part of the address is a memory dump on Windows!
# See https://bugs.ruby-lang.org/issues/21702
(@server.recvfrom(5) in ['hello', ['AF_UNIX', String]]).should be_true
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@trinistr trinistr force-pushed the 3.2-unixsocket-windows branch from 8092a25 to ba50fc1 Compare November 22, 2025 11:46
Previously, it was just a fancy :windows platform guard. Unix sockets are now mostly implemented on Windows, making the feature useless.
@trinistr trinistr force-pushed the 3.2-unixsocket-windows branch from ba50fc1 to 1d0c365 Compare November 22, 2025 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants