IO::Endpoint::Wrapper#bind always calls listen and handles EOPNOTSUPP, but in some environments, the error is translated to/propagated as EACCES#20
Open
Raekye wants to merge 1 commit into
Conversation
`IO::Endpoint::Wrapper.bind` always calls `Socket#listen`, and handles `Errno::EOPNOTSUPP`, for example for UDP sockets, for which the `listen` call is not applicable (see `man 2 listen`). However, in some environments, such as in a container, the error may be mapped to `EACCES`, which can be verified with a simple C program. This patch ignores `Errno::EACCES` if it was a UDP socket, since the `listen` call was meaningless in the first place.
17ed454 to
06e06f8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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