Skip to content

Commit 123f6c4

Browse files
bpo-37811: FreeBSD, OSX: fix poll(2) usage in sockets module (GH-15202)
FreeBSD implementation of poll(2) restricts the timeout argument to be either zero, or positive, or equal to INFTIM (-1). Unless otherwise overridden, socket timeout defaults to -1. This value is then converted to milliseconds (-1000) and used as argument to the poll syscall. poll returns EINVAL (22), and the connection fails. This bug was discovered during the EINTR handling testing, and the reproduction code can be found in https://bugs.python.org/issue23618 (see connect_eintr.py, attached). On GNU/Linux, the example runs as expected. This change is trivial: If the supplied timeout value is negative, truncate it to -1. (cherry picked from commit 2814620) Co-authored-by: Artem Khramov <[email protected]>
1 parent 557802d commit 123f6c4

File tree

3 files changed

+16
-0
lines changed

3 files changed

+16
-0
lines changed

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ Lawrence Kesteloot
832832
Garvit Khatri
833833
Vivek Khera
834834
Dhiru Kholia
835+
Artem Khramov
835836
Akshit Khurana
836837
Sanyam Khurana
837838
Mads Kiilerich
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix ``socket`` module's ``socket.connect(address)`` function being unable to
2+
establish connection in case of interrupted system call. The problem was
3+
observed on all OSes which ``poll(2)`` system call can take only
4+
non-negative integers and -1 as a timeout value.

Modules/socketmodule.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,17 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval,
780780
ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
781781
assert(ms <= INT_MAX);
782782

783+
/* On some OSes, typically BSD-based ones, the timeout parameter of the
784+
poll() syscall, when negative, must be exactly INFTIM, where defined,
785+
or -1. See issue 37811. */
786+
if (ms < 0) {
787+
#ifdef INFTIM
788+
ms = INFTIM;
789+
#else
790+
ms = -1;
791+
#endif
792+
}
793+
783794
Py_BEGIN_ALLOW_THREADS;
784795
n = poll(&pollfd, 1, (int)ms);
785796
Py_END_ALLOW_THREADS;

0 commit comments

Comments
 (0)