Backport #1567
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
=begin Symptom: TCPServer.new(...) may appear to succeed, even though its implied listen(2) call has silently failed. Similarly for UNIXServer.new(). Expectation: Failures in the underlying listen(2) call should translate to the appropriate ruby SystemCallError. Patch: The attached patch looks to me to address the issue under 1.9.1, and test/socket/* test cases all pass with it. Background: ext/socket/socket.c init_inetsock_internal() and init_unixsock() each conditionally call listen(2) but discard its return value. This behavior is incorrect, possibly leaving the caller with an unlistening socket when a listening one was expected, and inconsistent with the way those init_ functions handle failures of other implied socket calls, such as bind(2) or connect(2). It is tempting to omit error-checking listen(2) calls when the preceding, successful socket(2) and bind(2) calls are close by and visually verifiable (as in the init_* functions), since the most familiar listen(2) failures result from the programmer mistakenly operating on an inappropriate file descriptor. However, misbehaving threads can modify the file descriptor table behind our backs (EBADF), system/process failures do occur (ENOBUFS, EACCES) on some platforms, and LD_PRELOADed libraries may play wild tricks with socketry (EGOODLUCK). For these reasons, the init_ functions should rb_sys_fail when listen(2) fails. =end