Skip to content

Commit b0b178a

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 88cce7b commit b0b178a

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
@@ -815,6 +815,7 @@ Lawrence Kesteloot
815815
Garvit Khatri
816816
Vivek Khera
817817
Dhiru Kholia
818+
Artem Khramov
818819
Akshit Khurana
819820
Sanyam Khurana
820821
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
@@ -741,6 +741,17 @@ internal_select(PySocketSockObject *s, int writing, _PyTime_t interval,
741741
ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING);
742742
assert(ms <= INT_MAX);
743743

744+
/* On some OSes, typically BSD-based ones, the timeout parameter of the
745+
poll() syscall, when negative, must be exactly INFTIM, where defined,
746+
or -1. See issue 37811. */
747+
if (ms < 0) {
748+
#ifdef INFTIM
749+
ms = INFTIM;
750+
#else
751+
ms = -1;
752+
#endif
753+
}
754+
744755
Py_BEGIN_ALLOW_THREADS;
745756
n = poll(&pollfd, 1, (int)ms);
746757
Py_END_ALLOW_THREADS;

0 commit comments

Comments
 (0)