IO::Endpoint::Wrapper#bind always calls listen and handles EOPNOTSUPP, but in some environments, the error is translated to/propagated as EACCES
#20
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
IO::Endpoint::Wrapper.bindalways does bind and listen, and handlesErrno::EOPNOTSUPP, for example for UDP sockets, for whichlistenis not applicable. However, in some environments, such as in a container, the error may be mapped toEACCES, which as is, is not handled, basically causing the upper level program (e.g. aRubyDNSserver) to crash.This patch ignores
Errno::EACCESif it was a UDP socket, since thelistencall was meaningless in the first place.Example C program to compile and run in a container:
On my host system (Fedora 42), it prints "listen: Operation not supported" (
EOPNOTSUPP) as already handled, but in both afedora:42orubuntu:25.10container, it prints "listen: Permission denied" (EACCES).Author note: There currently defined socket types under
man 2 socketareSOCK_{STREAM,DGRAM,SEQPACKET,RAM,RDM}and the obsoluteSOCK_PACKET.man 2 listenindicates that it is only applicable to a socket of typeSOCK_STREAMorSOCK_SEQPACKET. This comment in the existing code explains whyWrapper#bindalways callslisten, and handlesEOPNOTSUPPafter:The code in this PR tries to be minimal in scope/change; it follows the existing control flow, by catching
EACCES(and checking if the socket type wasDGRAM), and it doesn't handleEACCESfor the other inapplicable socket types, since I figure realistically onlyDGRAMis relevant for users of this library, and also I haven't tested that the problem manifests in a container for those other socket types.However, especially since
EOPNOTSUPPis not reliable/comprehensive, it's arguablly better to wraplistenunder something likeif local_address.socktype == ServerSocket::SOCK_STREAM || local_address.socktype == ServerSocket::SOCK_SEQPACKET, matching the documentation forlisten(2), and removing the need forbegin...rescue.Types of Changes
Contribution