Project

General

Profile

Bug #16277

UNIXServer#listen fails with Errno::EADDRINUSE error under Windows 10 / WSL Ubuntu 18.04

Added by bradland (Brad Landers) about 2 months ago. Updated about 2 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux-gnu]
[ruby-core:95515]

Description

When running the following script under Windows 10 / WSL Ubuntu 18.04, an Errno::EADDRINUSE error is thrown. Expected result is that the script would run and simply exit.

#!/usr/bin/env ruby

# This script establishes a UNIX server socket.
# 
# Expected result: Script should run and immediately exit.
# 
# Actual result: Script fails with Errno::EADDRINUSE error.
# 
# Environment: Windows 10 Pro, WSL, Ubuntu 18.04.2, ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux-gnu]
# 
# To reproduce: Create a tmp folder, copy this script there, and execute.

require 'socket'

path = File.expand_path('listen.sock')
backlog = 5

s = UNIXServer.new(path)
if backlog
  s.listen backlog
else
  s.listen
end

File.delete(path) if File.exists?(path)

The bug was discoverd as part of Puma (gem) issue #1521: https://github.com/puma/puma/issues/1521.

History

Updated by shyouhei (Shyouhei Urabe) about 2 months ago

This is very nuanced. I'm not sure who is in charge of the exception.

UNIXServer.new's return value socket is already listened inside of the method. Calling listen again on a socket that is already listening, might or might not error depending on OS. That's why you see exceptions on WSL and not on Linux.

The problem I see is why at the beginning you want to listen again a socket returned from UNIXServer.new. I guess you want to change (maybe increase) the backlog? Then there seems to be no way for UNIXServer.new to change backlog than listening again. Is it possible for a WSL-hosted application to dynamically change the backlog per-socket? If not (== there is no way but to specify enough backlog at the birth), I guess this is a misfeature of UNIXServer.

Updated by MSP-Greg (Greg L) about 2 months ago

Would something like the following yield an equivalent object?

require 'socket'
sock = Socket.new :UNIX, :STREAM
sock.bind Addrinfo.unix('tmp.sock', :STREAM)
sock.listen 1024
puts sock.local_address.unix?

Also available in: Atom PDF